Skip to content

Redis Replication über Wireguard

Redis
  • Heutiges Kaffethema, Redis Replication über Wireguard 🙂

    Die Idee / Das Problem

    Ich setze als eine Sicherung der Daten der Redis Datenbank, die Redis Funktion Replication ein.

    Redis tauscht die Daten im Klartext aus!

    Da ich das weiß, hatte ich die Kommunikation zwischen zwei Servern in der Hetzner Cloud über ein privates Netz abgewickelt. Da ich aber da nicht sicher bin, wer da so alles dran käme, machen wir das Ganze noch einen Tick sicherer 😉

    Vorab, man kann die Serververbindung auch mittels TLS absichern. Da ich aber ein großer Freund von Wireguard bin, machen wir es mit einem verschlüsselten Tunnel 🙂 So bleibt man in Übung...

    Installation Wireguard

    Meine Server sind alle Debian Buster 10.

    apt install linux-headers-$(uname -r)
    apt install wireguard
    

    Danach die Kisten durchstarten. Siehe die Ergänzungen / Kommentare weiter unten!

    Kontrolle

    lsmod | grep wireguard
    wireguard             225280  0
    ip6_udp_tunnel         16384  1 wireguard
    udp_tunnel             16384  1 wireguard
    

    Wireguard Konfiguration

    Server 1 (Redis Master)

    [Interface]
    #Address = 10.10.1.2
    PrivateKey = <private Key>
    ListenPort = 58380
    
    [Peer]
    PublicKey = <public Key>
    PresharedKey = <PSK Key>
    Endpoint = <IP vom Endpoint>:58380
    AllowedIPs = 10.10.1.1/32
    

    Server 2 (Redis Slave)

    [Interface]
    #Address = 10.10.1.1
    PrivateKey = <private Key>
    ListenPort = 58380
    
    [Peer]
    PublicKey = <public Key>
    PresharedKey = <PSK Key>
    Endpoint = <IP vom Endpoint>:58380
    AllowedIPs = 10.10.1.2/32
    

    Wireguard starten

    ip link add dev wg0 type wireguard
    ip link set up dev wg0
    wg-quick up wg0
    

    Testen

    wg
    interface: wg0
      public key: <public Key>
      private key: (hidden)
      listening port: 58380
    
    peer: <peer Key>
      endpoint: <IP>:58380
      allowed ips: 10.10.1.2/32
      latest handshake: 1 minute, 39 seconds ago
      transfer: 66.83 MiB received, 839.15 KiB sent
    

    Ok, das funktioniert so weit.

    Redis Konfiguration

    Master

    bind 127.0.0.1 ::1 10.10.1.2
    

    Slave

    bind 127.0.0.1 ::1 10.10.1.1
    replicaof 10.10.1.2 6379
    

    Beide Redis Instanzen ausschalten

    service redis stop
    

    Danach erst den Master starten, danach den Slave.

    service redis start
    

    Kontrolle /var/log/redis/redis-server.log

    3643:S 06 Jun 2020 08:44:05.673 * Discarding previously cached master state.
    3643:S 06 Jun 2020 08:44:06.089 * MASTER <-> REPLICA sync: receiving 21888363 bytes from master
    3643:S 06 Jun 2020 08:44:06.549 * MASTER <-> REPLICA sync: Flushing old data
    3643:S 06 Jun 2020 08:44:06.780 * MASTER <-> REPLICA sync: Loading DB in memory
    3643:S 06 Jun 2020 08:44:07.323 * MASTER <-> REPLICA sync: Finished with success
    3643:S 06 Jun 2020 08:49:06.054 * 10 changes in 300 seconds. Saving...
    3643:S 06 Jun 2020 08:49:06.058 * Background saving started by pid 3775
    3775:C 06 Jun 2020 08:49:06.527 * DB saved on disk
    3775:C 06 Jun 2020 08:49:06.530 * RDB: 10 MB of memory used by copy-on-write
    3643:S 06 Jun 2020 08:49:06.559 * Background saving terminated with success
    3643:S 06 Jun 2020 08:54:07.033 * 10 changes in 300 seconds. Saving...
    3643:S 06 Jun 2020 08:54:07.036 * Background saving started by pid 3885
    3885:C 06 Jun 2020 08:54:07.623 * DB saved on disk
    

    So MUSS das aussehen. Wenn ihr so was seht

    3312:S 06 Jun 2020 08:43:45.231 * Connecting to MASTER 10.10.1.2:6379
    3312:S 06 Jun 2020 08:43:45.231 * MASTER <-> REPLICA sync started
    3312:S 06 Jun 2020 08:43:45.232 # Error condition on socket for SYNC: Connection refused
    

    dann habt ihr ein Kommunikationsproblem. Firewall usw.

    iptables

    Master

    1. Wir erlauben Wireguard

       #=========================
       # Wireguard (IN) from Datenbank Server
       #=========================
       $IP4TABLES -A INPUT -p udp --src <IPv4> --dport 58380 -j ACCEPT
      
    2. Wir erlauben Redis-Replication

       #=========================
       # Redis-Server Replication Port (IN) from Datenbank Server
       #=========================
       $IP4TABLES -A INPUT -p tcp --src 10.10.1.1 --dport 6379 -j ACCEPT
      

    Slave

    Wir erlauben Wireguard

        #=========================
        # Wireguard (IN) from Webserver2
        #=========================
        $IP4TABLES -A INPUT -p udp --src <IPv4> --dport 58380 -j ACCEPT
    

    Nicht vergessen, die Regeln dauerhaft abzuspeichern. Ich mache das so -> https://forum.frank-mankel.org/topic/661/iptables-dauerhaft-speichern

    Das ist eine sehr knapp gefasste Version, dessen was man machen muss. Für Einsteiger vermutlich ungeeignet, lest bitte in dem Fall die anderen Beiträge von mir zu den Themen.

    Was hier jetzt noch nicht abgehandelt ist, der Wireguard Tunnel startet nicht wenn der Server neugestartet wird. Kommt noch ...

    ToDo (für mich) 😉

    Wireguard bei Server Neustart starten

    In /etc/network/interfaces.d/ die Datei 70-wg0.cfg erzeugen.

    # Wireguard
    auto wg0
    iface wg0 inet static
            address 10.10.1.1
            netmask 255.255.255.0
            pre-up ip link add $IFACE type wireguard
            pre-up wg setconf $IFACE /etc/wireguard/$IFACE.conf
            post-down ip link del $IFACE
    

    Beim nächsten Start steht der Wireguard Tunnel automatisch. Bitte drauf achten, wenn man das so macht, braucht man in der wg0.conf keine Zuordnung der IP-Adresse. Ich habe diese oben auskommentiert.

    psk Key

    Was ist das?

    If an additional layer of symmetric-key crypto is required (for, say, post-quantum resistance), WireGuard also supports an optional pre-shared key that is mixed into the public key cryptography. When pre-shared key mode is not in use, the pre-shared key value used below is assumed to be an all-zero string of 32-bytes.

    Für mich, als nicht Sicherheitsexperte, liesst sich das so: Dieser Key erhöht die Sicherheit. So mit ist es sicherlich sinnvoll diesen immer mit anzugeben.

    Oben in der Konfiguration den PSK Key hinzugefüht. Der muss auf beiden Seiten gleich sein.

    interface: wg0
      public key: <public Key>
      private key: (hidden)
      listening port: 58380
    
    peer: <perr Key>
      preshared key: (hidden)
      endpoint: <IPv4>:58380
      allowed ips: 10.10.1.1/32
      latest handshake: 35 seconds ago
      transfer: 205.20 KiB received, 22.28 MiB sent
    
  • @FrankM sagte in Redis Replication über Wireguard:

    die Kisten durchstarten

    moin,
    vermutlich offtopic, entschuldigung: Du musst vermutlich bei einem install nicht "die Kisten durchstarten". Habe das schon öfter gelesen und sah oft keinen grund dafür. So nach aktuellem Kenntnisstand auch hier, wenn du das modul reinwerfen kannst/musst zu laufzeit (modprobe/insmod) und den service starten, warum sollte das nicht gehen..

    man kann aber auch falsch liegen, richtig
    gruß

  • @kosmonaut-pirx Ich denke, du liegst da richtig. DKMS baut ja das Kernelmodul und lädt es danach auch!? Damit sollte dieser Schritt überflüssig sein.

    Da ich das Morgen auf einem weiteren Server einbaue, werde ich das mal beobachten 😉

  • Guten Morgen. Oben noch meine ToDo-Liste abgearbeitet 😉

    Zum Kernelmodul. Das wird ja von DKMS gebaut.

    Building initial module for 4.19.0-9-amd64
    Done.
    
    wireguard.ko:
    Running module version sanity check.
     - Original module
       - No original module exists within this kernel
     - Installation
       - Installing to /lib/modules/4.19.0-9-amd64/updates/dkms/
    
    depmod....
    
    DKMS: install completed.
    Setting up wireguard (1.0.20200513-1~bpo10+1) ...
    Processing triggers for man-db (2.8.5-2) ...
    

    Danach ist das Kernelmodul installiert.

    dkms status wireguard
    wireguard, 1.0.20200506, 4.19.0-9-amd64, x86_64: installed
    

    Das Modul ist aber nicht geladen.

    lsmod | grep wireguard
    

    ist leer! Erst ein

    modprobe wireguard
    

    lädt das Kernelmodul.

    lsmod | grep wireguard
    wireguard             225280  0
    ip6_udp_tunnel         16384  1 wireguard
    udp_tunnel             16384  1 wireguard
    

    @kosmonaut-pirx Ich denke, du hast Recht, auf den Server Neustart kann verzichtet werden. Man lernt nie aus 🙂

  • 👍
    spart bischen zeit

  • 0 Votes
    3 Posts
    92 Views
    FrankMF

    Ich bin mit der Lernkurve noch nicht so richtig zufrieden. Eine Frage die sich mir stellte, geht das einfacher? Der Ursprung meiner Datenbank Struktur liegt in einem anderen Projekt, wo ich versucht habe Daten permanent in einem File zu speichern. Dazu hatte ich damals JSON genommen. Deswegen auch diese Zeilen

    self.project = str(db_client.json().get('settings', '$..project')[0]) or self.project

    Gut, ich hatte dann mal ChatGPT gefragt, wie macht man das so 'normalerweise'? es kam eine Klasse heraus, die ich dann intensiv ausprobiert habe, ein wenig umgebaut usw. So lange, bis ich der Meinung war, ok ich habe es verstanden. Jetzt nutzte der Code auch mehr Redis Funktionen, wie

    self.client.hset('settings', name, json.dumps(data))

    Es waren jetzt folgende Funktionen drin

    hset hexists hdel hget

    Dokumentation -> https://redis.io/commands/hset/

    Beim Durchlesen des Codes hatte ich jetzt mehr das Gefühl, so muss das sein 🙂

    In RedisInsight sieht das dann jetzt so aus.

    393195f7-1017-4285-8fca-734ee6b4bff7-grafik.png

    Klasse class PortfolioSettings: def __init__(self, host='172.17.0.2', port=6379, db=0): if args.test_mode == 1: self.client = redis.StrictRedis(host=SERVER_IP, port=port, db=TEST[0]) else: self.client = redis.StrictRedis(host=SERVER_IP, port=port, db=LIVE[0]) def set_settings(self, name, data): """Init settings if db don't exist""" if not self.client.hexists('settings', name): self.client.hset('settings', name, json.dumps(data)) return True return False def edit_setting(self, name, data): """Edit an entry in settings""" if self.client.hexists('settings', name): self.client.hset('settings', name, json.dumps(data)) return True return False def delete_setting(self, name): """Delete an entry in settings""" return self.client.hdel('settings', name) def get_setting(self, name): """Get an entry in settings""" setting = self.client.hget('settings', name) return json.loads(setting) if setting else None def get_all_settings(self): """Get all entries in settings""" settings = self.client.hgetall('settings') return {k.decode(): json.loads(v) for k, v in settings.items()}

    Und hier die Initialisierung

    settings_data = PortfolioSettings() ##################### # Will only be executed if DB is not available! ##################### if not settings_data.get_all_settings(): # Settings initialisieren print("INIT") settings_data.set_settings("project", "Portfolio") settings_data.set_settings("version", "0.0.3") settings_data.set_settings("theme", "dark") settings_data.set_settings("url_list", ["https://www.onvista.de/aktien/Deutsche-Telekom-Aktie-DE0005557508"]) settings_data.set_settings("exchange_list", ['DKB','Smartbroker','BUX'])

    Teile der Klasse sind [KI-generiert]

    Ich war zufrieden und habe die Klasse dann in mein Projekt übernommen und den Code überall entsprechend angepasst.

  • 0 Votes
    1 Posts
    166 Views
    No one has replied
  • NodeBB - Zwei Instanzen

    Pinned NodeBB
    1
    0 Votes
    1 Posts
    90 Views
    No one has replied
  • Redis - Datenbanken löschen

    Redis
    1
    0 Votes
    1 Posts
    132 Views
    No one has replied
  • Redis - Sicherheitsupdate Debian

    Redis
    1
    0 Votes
    1 Posts
    120 Views
    No one has replied
  • RedisInsight

    Redis
    1
    0 Votes
    1 Posts
    163 Views
    No one has replied
  • Wireguard - Traffic routen

    Wireguard
    2
    0 Votes
    2 Posts
    1k Views
    FrankMF

    Wie ich bei meinem Hamburger Systemadministrator gelernt habe, geht das auch wesentlich einfacher. Dafür hat Wireguard einen netten Befehl schon parat, nennt sich

    wg-quick up wg0-client

    Dazu muss auf dem Client natürlich vorher alles konfiguriert sein. Das Verzeichnis /etc/wireguard sieht dann so aus.

    root@thinkpad:/etc/wireguard# ls -lha /etc/wireguard/ insgesamt 32K drwx------ 2 root root 4,0K Aug 16 08:47 . drwxr-xr-x 141 root root 12K Aug 16 08:47 .. -rw-r--r-- 1 root root 45 Aug 9 16:48 private.key -rw-r--r-- 1 root root 45 Aug 9 16:48 psk.key -rw-r--r-- 1 root root 45 Aug 9 16:48 public.key -rw-r--r-- 1 root root 275 Aug 16 08:47 wg0-client.conf

    Die drei Schlüssel sind also vorhanden, der Server ist auch entsprechend vorbereitet. Dann brauchen wir auf dem Clienten noch die wg0-client.conf mit folgendem Inhalt.

    [Interface] Address = 10.10.0.4/32 PrivateKey = oM9jWxxxxxxxxxxxxxxxxxxxxxxxxxxxtS4vW8= ListenPort = 50xxx DNS = 10.10.0.2 [Peer] PublicKey = fGg7MxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxTPRqqzU= Endpoint = 136.xxx.xxx.xxx:60xxx AllowedIPs = 0.0.0.0/0 PersistentKeepalive = 21

    Im ersten Teil [Interface] wird die Schnittstelle auf dem Clienten konfiguriert.

    Die Adresse des Clienten Privatekey, findet man in /etc/wireguard/private.key Den Port für die Wireguard Kommunikation, frei wählbar. Der DNS-Server, ist hier mein Wireguard-Server, der einen DNS Dienst bereit hält.

    Im zweiten Teil [Peer] wird die Verbindung zum Server konfiguriert.

    PublicKey, der PublicKey des Servers. Endpoint, ist die IP-Adresse des Servers. AllowedIPs 0.0.0./0 wird den gesamten IPv4 Verkehr über den Tunnel routen. Dient dazu , die Verbindung aufrecht zu erhalten?

    Mit

    wg-quick up wg0-client

    baut er nun die Verbindung auf.

    root@thinkpad:/etc/wireguard# wg-quick up wg0-client [#] ip link add wg0-client type wireguard [#] wg setconf wg0-client /dev/fd/63 [#] ip -4 address add 10.10.0.4/32 dev wg0-client [#] ip link set mtu 1420 up dev wg0-client [#] resolvconf -a tun.wg0-client -m 0 -x [#] wg set wg0-client fwmark 51xxx [#] ip -4 route add 0.0.0.0/0 dev wg0-client table 51xxx [#] ip -4 rule add not fwmark 51xxx table 51xxx [#] ip -4 rule add table main suppress_prefixlength 0 root@thinkpad:/etc/wireguard#

    Damit steht der Tunnel

    9: wg0-client: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000 link/none inet 10.10.0.4/32 scope global wg0-client valid_lft forever preferred_lft forever

    Ausschalten

    root@thinkpad:/etc/wireguard# wg-quick down wg0-client [#] ip -4 rule delete table 51xxx [#] ip -4 rule delete table main suppress_prefixlength 0 [#] ip link delete dev wg0-client [#] resolvconf -d tun.wg0-client

    Auf meinem Debian 10 Buster ging das erst so nicht, weil ein Paket fehlt.

    root@thinkpad:/etc/wireguard# wg-quick up wg0-client [#] ip link add wg0-client type wireguard [#] wg setconf wg0-client /dev/fd/63 [#] ip -4 address add 10.10.0.4/32 dev wg0-client [#] ip link set mtu 1420 up dev wg0-client [#] resolvconf -a wg0-client -m 0 -x /usr/bin/wg-quick: line 31: resolvconf: command not found [#] ip link delete dev wg0-client

    Wireguard ist so nett und schreibt alles rein 😉 Eine Installation von resolcconf löst das Problem.

    root@thinkpad:/etc/wireguard# apt install resolvconf Paketlisten werden gelesen... Fertig Abhängigkeitsbaum wird aufgebaut. Statusinformationen werden eingelesen.... Fertig Die folgenden NEUEN Pakete werden installiert: resolvconf 0 aktualisiert, 1 neu installiert, 0 zu entfernen und 0 nicht aktualisiert. Es müssen 74,2 kB an Archiven heruntergeladen werden. Nach dieser Operation werden 196 kB Plattenplatz zusätzlich benutzt. [gekürzt]

    Nun kann man den Tunnel mit zwei einfachen Befehlen auf- und wieder abbauen. Als nächstes kommt dann noch die IPv6 Erweiterung, weil im Moment IPv6 Traffic am Tunnel vorbei fliessen würde, wenn man eine öffentliche IPv6 Adresse zugewiesen bekommen hätte. Aber, das muss ich mir noch ein wenig erklären lassen 🙂

  • Redis Datenbank sichern

    Moved Redis
    1
    0 Votes
    1 Posts
    746 Views
    No one has replied