Περί τίνος πρόκειται;
Παρακολούθηση του ιστορικου τοποθεσίας τόσο τις δική σας όσο και της οικογένειας/φίλων σας και εμφάνιση του ιστορικου τοποθεσιών στο χάρτη. Μια εναλλακτική λύση ανοιχτού κώδικα για το Google maps history
- Το Owntracks είναι μια εφαρμογή παρακολούθησης ιστορικού τοποθεσίας
- Το Mosquitto είναι ένας brocker μηνυμάτων δημοσίευσης/εγγραφής πρωτόκολλου mqtt, ο οποιος αποθηκεύει δεδομένα που λαμβάνει από πελάτες
- Το Recorder είναι ένα ελαφρύ πρόγραμμα για την αποθήκευση και πρόσβαση σε δεδομένα τοποθεσίας που δημοσιεύονται μέσω MQTT (ή HTTP) και τα εμφανίζει σε μια διαδικτυακή διεπαφή χρήστη σε έναν χάρτη ως ίχνη, σημεία κ.λπ.
- Η εφαρμογή Android παρακολουθεί την τοποθεσία και στέλνει τα δεδομένα τοποθεσίας στο mosquitto, στη συνέχεια ο recorderλαμβάνει τα δεδομένα από το mosquitto και τα εμφανίζει γραφικά σε ένα webui
- Το mTLS χρησιμοποιείται για τον έλεγχο ταυτότητας πελατών, ενώ το “κανονικό” TLS απλώς ελέγχει την ταυτότητα του διακομιστή. Ο έλεγχος ταυτότητας είναι πλέον αμοιβαίος!
- Το mTLS είναι ένα από τα κομμάτια του παζλ για τη δημιουργία ενός Δικτύου Μηδενικής Εμπιστοσύνης καθώς ελέγχει αυστηρά ποιους πελάτες επιτρέπεται να συνδέονται σε μια υπηρεσία ανεξάρτητα από το από πού συνδέεται ένας χρήστης ή συσκευή
- στις παρακάτω ρυθμίσεις η εφαρμογή android συνδέεται με mtls με το mosquitto και το πρόγραμμα περιήγησης συνδέεται με mtls με το webui μέσω του caddy
- Ο Caddy 2 είναι ένας ισχυρός διακομιστής ιστού ανοιχτού κώδικα με αυτόματο HTTPS γραμμένος σε Go
- Το Recorder υποστηρίζει επίσης tls, αλλά υπέφερα προσπαθώντας να το κάνω να λειτουργήσει χωρίς επιτυχία, καθώς η επικοινωνία με το mosquitto πραγματοποιήται μόνο μέσα στο LAN μας και είναι προστατευμένο με basic auth, είμαι ok με την συγκεκριμένο setup
Δημιουργήστε τα πιστοποιητικά για το mosquitto και την εφαρμογή android
- script
nano certs.sh
Paste
#!/bin/bash
IP="your_lan_ip"
SUBJECT_CA="/C=SE/ST=Athens/L=Athens/O=ippo/OU=CA/CN=$IP"
SUBJECT_SERVER="/C=SE/ST=Athens/L=Athens/O=ippo/OU=Server/CN=$IP"
SUBJECT_CLIENT="/C=SE/ST=Athens/L=Athens/O=ippo/OU=Client/CN=$IP"
function generate_CA () {
echo "$SUBJECT_CA"
openssl req -x509 -nodes -sha256 -newkey rsa:2048 -subj "$SUBJECT_CA" -days 3650 -keyout ca.key -out ca.crt
}
function generate_server () {
echo "$SUBJECT_SERVER"
openssl req -nodes -sha256 -new -subj "$SUBJECT_SERVER" -keyout server.key -out server.csr
openssl x509 -req -sha256 -in server.csr -CA ca.crt -extfile v3.ext -CAkey ca.key -CAcreateserial -out server.crt -days 3650
}
function generate_client () {
echo "$SUBJECT_CLIENT"
openssl req -new -nodes -sha256 -subj "$SUBJECT_CLIENT" -out client.csr -keyout client.key
openssl x509 -req -sha256 -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 3650
}
generate_CA
generate_server
generate_client
- Αντικατέστησε τα IP και ST,L,O για τα ca,server,client crt επίσης διάλεξε μια επιθυμητή διαρκεια -days για αυτα
- το αρχείο ext πρεπει να βρίσκεται στο ίδιο dir με το script
- Αντέγραψε τα ca.crt,server.crt,server.key στο mosquitto/config
Το αρχείο ext για τη συμπλήρωση του πεδίου S.A.N.
nano v3.ext
Paste
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
basicConstraints = CA:TRUE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment, keyAgreement, keyCertSign
subjectAltName = DNS:mqtt.example.org
issuerAltName = issuer:copy
- Στο πεδίο subjectAltName βάλε την dynamic dns διεύθυνση απο την οποία θα σύνδεσε στο mosquitto
- Αυτο ειναι θεμελιώδες μιας και μονο Οσα domain αναγράφονται σε αυτο το πεδίο θα μπορούν να κανουν χρηση του πιστοποιητικού
Κάνε το script εκτελέσιμο και τρέξε το
chmod +x certs.sh
bash certs.sh
Δημιούργησε ενα pkcs12 bundle απο το client cert
openssl pkcs12 -export -out cert.p12 -inkey client.key -in client.crt -legacy
- Μετέφερε τα ca.crt και cert.p12 στην συακευη android
- Εγκατεστησε το ca.crt απο android>settings>security>encryption>install a certificate>ca certificate
- Επέλεξε το cert.p12 απο owntracks>preferences>connection>security
- Το Android δεν μπορεί να διαχειριστεί τους μοντέρνους pkcs encryption αλγορίθμους (PBES2, PBKDF2, AES-256-CBC, Iteration 2048, PRF hmacWithSHA256) οι οποίοι χρησιμοποιούνται απο το openssl v3 . Μπορεις να παραλήψεις το -legacy flag αν θα δημιουργήσεις τα πιστοποιητικά με παλαιότερη έκδοση openssl
Δημιουργία φακέλων και αρχείων
mkdir {config,mosquitto,store,store/last}
Δημιουργία του confoguration αρχείου του recorder
nano config/recorder.conf
Paste
OTR_TOPICS = "owntracks/#"
OTR_HTTPHOST = "0.0.0.0"
OTR_HOST = "your lan ip"
OTR_USER = "user"
OTR_PASS = "pass"
Δημιουργία του confoguration αρχείου του mosquitto
nano mosquitto/config/mosquitto.conf
Paste
persistence true
persistence_location /mosquitto/data/
listener 1883
password_file /mosquitto/passwd/pass
listener 8883
cafile /mosquitto/config/ca.crt
certfile /mosquitto/config/server.crt
keyfile /mosquitto/config/server.key
require_certificate true
use_identity_as_username true
protocol websockets
Δημιουργία του αρχειου compose
nano docker-compose.yml
Paste
version: '3'
services:
mosquitto:
image: eclipse-mosquitto:openssl
container_name: mosquitto
restart: unless-stopped
ports:
- "1883:1883"
- "8883:8883"
volumes:
- "./mosquitto/config:/mosquitto/config"
- "./mosquitto/data:/mosquitto/data"
- "./mosquitto/config/passwd:/mosquitto/passwd"
environment:
- TZ=Europe/Athens
user: "1000:1000"
otrecorder:
image: ot-arm:latest
ports:
- 8083:8083
volumes:
- ./config:/config
- ./store:/store
restart: unless-stopped
Δημιουργία και build του recorder image
nano Dockerfile
Paste
FROM alpine:3.16 AS builder
ARG RECORDER_VERSION=0.9.3
# ARG RECORDER_VERSION=master
RUN apk add --no-cache \
make \
gcc \
git \
shadow \
musl-dev \
curl-dev \
libconfig-dev \
mosquitto-dev \
lmdb-dev \
libsodium-dev \
lua5.2-dev \
util-linux-dev
RUN git clone --branch=${RECORDER_VERSION} https://github.com/owntracks/recorder /src/recorder
WORKDIR /src/recorder
COPY config.mk .
RUN make -j $(nprocs)
RUN make install DESTDIR=/app
FROM alpine:3.16
VOLUME ["/store", "/config"]
RUN apk add --no-cache \
curl \
jq \
libcurl \
libconfig \
mosquitto \
lmdb \
libsodium \
lua5.2 \
util-linux
COPY recorder.conf /config/recorder.conf
COPY JSON.lua /config/JSON.lua
COPY --from=builder /app /
COPY recorder-health.sh /usr/sbin/recorder-health.sh
COPY entrypoint.sh /usr/sbin/entrypoint.sh
RUN chmod +x /usr/sbin/*.sh
RUN chmod +r /config/recorder.conf
# If you absolutely need health-checking, enable the option below. Keep in
# mind that until https://github.com/systemd/systemd/issues/6432 is resolved,
# using the HEALTHCHECK feature will cause systemd to generate a significant
# amount of spam in the system logs.
# HEALTHCHECK CMD /usr/sbin/recorder-health.sh
EXPOSE 8083
# ENV OTR_CAFILE=/etc/ssl/cert.pem
ENV OTR_STORAGEDIR=/store
ENV OTR_TOPIC="owntracks/#"
ENTRYPOINT ["/usr/sbin/entrypoint.sh"]
- Το owntracks recorder δημοσιεύει x86 images στο dockerhub ομως δεν υπάρχει official ARM image
- Το mosquitto δημοσιεύει images γιανολα τα aarch
Δημιουργία και ονομασια του recorder image
docker build -t ot-arm
Τρεχούμενα το compose file
docker compose up
- Κανουμε Comment το password_file στο mosquitto/config/mosquitto.conf στην πρώτη εκτέλεση και εκτελούμε την εντολή mosquitto_passwd ως χρήστης root στο mosquitto container και έπειτα κάνουμε uncomment το password_file και ξανατρεχουμε docker compose up
Δημιουργία user/pass για τον recorder στο mosquitto
docker exec -it --user root mosquitto mosquitto_passwd -c /mosquitto/passwd/pass username
- Τώρα μπορούμε να τρέξουμε το conatainer detached
docker compose up -d
android app settings
Connection:
-
mode mqtt
-
host mqtt.example.org
-
Port 8883 (ανοιχτή πόρτα στο router)
-
Client ID random name
-
Ενεργοποιω το διακόπτη Websockets
Identification:
-
Username random name
-
Password κενό
-
Device ID random name (μαζί με το username εμφανιζεται ως username/deviceID στη λίστα με τα tracks στον recorder)
-
Tracker ID random name (Συνηθος δυο γραμματα. Εμφανιζεται ως εικονίδιο ατο χαρτη)
Security:
-
Διακοπτης TLS ενεργός
-
Επιλέγω το client cert απο preferences>connection>security
-
CA cert κενό (εγκαθιστω το ca.crt στο user store της συακευης)
Πρόσβαση στο webui
- Ρύθμιση το caddy για reverse proxy and mutual TLS proxied υπηρεσίες και εγκαθιστω το client cert του recorder στο android
Δημιουργία των certs
- Αίτηση ενος νεου key and crt
openssl req -x509 -newkey rsa:4096 -keyout cert_name.key -out cert_name.crt -days 365
- Αίτηση ενος νεου certificate signing request
openssl req -new -key cert_name.key -out cert_name.CSR
- Αίτηση ενος νεου certificate authority
openssl x509 -req -days 365 -in cert_name.csr -signkey cert_name.key -out cert_name-CA.crt
- Δημιουργία pem certificate
cat cert_name.crt cert_name.key > cert_name.pem
- Δημιουργια pkcs12 certificate
openssl pkcs12 -export -out cert_name.p12 -inkey cert_name.key -in cert_name.pem -legacy
- Στο android πρεπει να εγκαταστήσεις το cert_name.p12 cert ως vpn & app user certificate στο settings > security > more > credentials > install > VPN & app user cert
- Μη ξεχάσεις να αντιγραψεις τα cert_name-CA.crt και cert_name.crt στο /var/lib/caddy/cert/
Προσθήκη του certificate directive στο caddyfile και reverse proxy το subdomain του webui του recorder στην πόρτα που αυτός τρέχει (8083) στη localhost
nano /etc/caddy/Caddyfile
#cert directive
(fancy_name) {
tls {
client_auth {
mode require_and_verify
trusted_ca_cert_file /var/lib/caddy/cert/cert_name-CA.crt
trusted_leaf_cert_file /var/lib/caddy/cert/cert_name.crt
}
}
}
#owntracks
owntracks.example.org {
import fancy_name
reverse_proxy localhost:8083
}
- Μπορείς να δεις το ιστορικό τοποθεσίας επισκεπτοντας την owntracks.example.org
domains
- Χρησιμοποιήσαμε δυο domains
- Ενα για τη δημοσίευση mqtt messages τοποθεαιας απο το android στο mosquitto (mqtt.example.org)
- και ενα για την πρόσβαση στο webui του recorder απο τον browser (owntracks.example.org)
certificates
- Εγκαταστησαμε δυο πιστοποιητικά στο android certificate store
- Το certificate authority για το client cert του mosquitto (ca.crt )
- Το client certificate του caddy (cert_name.p12)
- Επιλέξαμε το mosquitto client cert μεαα απο την εφαρμογή owntracks (cert.p12)
- Δημιουργησαμε δυο certificate authorities.
- Το caddy directive “fancy_name” μπορουμε να το χρησιμοποιείσουμε και σε αλλες υπηρεσίες τις οποίες κάνουμε reverse proxy με το caddy εισάγοντας “import fancy_name” στο reverse proxy directive
Δομή των φακέλων
ls -R
.:
config docker-compose.yml mosquitto store
./config:
recorder.conf
./mosquitto:
config data
./mosquitto/config:
ca.crt mosquitto.conf passwd server.crt server.key
./mosquitto/config/passwd:
pass
./mosquitto/data:
./store:
ghash last monitor rec
./store/ghash:
data.mdb lock.mdb
Πηγες
Τα παραπανω ειναι μια συραφή και προσαρμογή απο διάφορες πηγές