Die Installation des Gateways ist noch nicht abgeschlossen, deswegen ist dieser Wiki-Eintrag noch nicht fertiggestellt. Änderungen sind möglich, ebenso können noch Fehler enthalten sein.
<
Voraussetzungen
Im Folgenden wird das Aufsetzen eines Gateways (gw1) beschrieben. Beispielhaft verwenden wir Gentoo, dabei wird von Grundinstallation laut Gentoo Handbuch ausgegangen. Empfohlen wird die Nutzung eines Hardened Profiles.
Die einzelnen Konfigurationsdateien werden zentral in einem Git-Repository und können dort eingesehen werden.Dort befindet sich auch ein Gentoo-Portage-Overlay für Freifunk-spezifische Ebuilds. Diese wird wie folgt eingebunden:
emerge -av layman
Nach der Layman-Installation wird angezeigt, wie dies in der Portage-Konfiguration (/etc/portage/make.conf) integriert wird. Danach wird das Overlay eingebunden:
# cd /etc/layman/overlays # wget https://raw.githubusercontent.com/ffggrz/ff-overlay/master/ff-overlay.xml # layman -L # layman -a ff-overlay
Grundkonfiguration
Hostname
Der Hostname wird in /etc/conf.d/hostname gesetzt:
# Set to the hostname of this machine hostname="gw1"
/etc/hosts sollte etwa so aussehen:
# IPv4 and IPv6 localhost aliases # 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback ff02::1 ip6-allnodes ff02::2 ip6-allrouters # own external addresses 148.251.158.22 gw1.freifunk-gera-greiz.de gw1 2a01:4f8:210:5132:201::22 gw1.freifunk-gera-greiz.de gw1 # Freifunk external 78.46.192.49 gw2.freifunk-gera-greiz.de gw2 2a01:4f8:c17:229::12 gw2.freifunk-gera-greiz.de gw2 # Freifunk internal 10.181.0.1 nextnode.ffggrz fdb5:078b:64cc::1 nextnode.ffggrz 10.181.0.11 gw1.ffggrz 1.ntp.services.ffggrz 1.updates.services.ffggrz fdb5:78b:64cc::11 gw1.ffggrz 1.ntp.services.ffggrz 1.updates.services.ffggrz 10.181.0.12 gw2.ffggrz 2.ntp.services.ffggrz 2.updates.services.ffggrz fdb5:78b:64cc::12 gw2.ffggrz 2.ntp.services.ffggrz 2.updates.services.ffggrz 10.181.0.101 raspbx.ffggrz fdb5:78b:64cc::101 raspbx.ffggrz
Hier werden also, jeweils für IPv4 und IPv6, die Namen für die localhost-Adressen, die externen Adressen im Internet und die Freifunk-internen Adressen definiert. Am Ende folgen noch Einträge für alle Host, welche der später per DNSmasq arbeitende DNS-Server auflösen soll.
Routing
/etc/iproute2/rt_tables:
# # reserved values # 255 local 254 main 253 default 0 unspec # # local # # local community tables 181 ggrz # # icvpn table 42 icvpn # # ffrl table (Exit per FFRL) 83 ffrl
Hier wurden separate Routing-Tabellen für das lokale Mesh-Netzwerk (181, ggrz), das Intercity-VPN (42, icvpn) und den Exit per Freifunk Rheinland e.V. (83, ffrl) definiert. Nur so kann später erreicht werden, daß dieses Gateway als Default Gateway für alle Clients fungiert und deren Traffic nicht über das "normale" Internet routet, sondern über ein Exit-VPN per Tunnel ins Ausland oder zu einem der Freifunk-Vereine mit Provider-Status.
Kernelparameter
Unter Gentoo bauen wir den Kernel selbst. Neben der Grundkonfiguration, um die verwendete Hardware bzw. den Virtualisierungs-Host oder Grundfunktionen wie Netzwerk mit IPv6 zu unterstützen, brauchen wir folgende Optionen:
[*] Networking support ---> Networking options ---> <*> TCP/IP networking [*] IP: multicasting [*] IP: advanced router [*] IP: policy routing <*> The IPv6 protocol ---> [*] IPv6: multiple routing tables <*> 802.1d Ethernet Bridging Device Drivers ---> [*] Network device support ---> [*] Network core driver support <*> Universal TUN/TAP device driver support
Sicherlich fehlen hier noch viele andere erforderliche Parameter. Ein Beispiel einer funktionierenden (aber sicher auch nicht optimalen) Konfiguration findet sich hier: linux-3.18.9-hardened.config. Die aktuelle Konfiguration ist im Git-Repository zu finden.
Folgende Einstellungen in /etc/sysctl.conf sind erforderlich:
# Freifunk specific settings net.ipv4.ip_forward = 1 net.ipv4.conf.default.rp_filter = 2 net.ipv4.conf.all.rp_filter = 2 net.bridge.bridge-nf-call-arptables = 0 net.bridge.bridge-nf-call-ip6tables = 0 net.bridge.bridge-nf-call-iptables = 0 net.ipv6.conf.all.forwarding = 1 net.ipv6.conf.all.autoconf = 0 net.ipv6.conf.default.autoconf = 0 net.ipv6.conf.eth0.autoconf = 0 net.ipv6.conf.all.accept_ra = 0 net.ipv6.conf.default.accept_ra = 0 net.ipv6.conf.eth0.accept_ra = 0
Damit wird das Routing (Forwarding) für IPv4 und IPv6 aktiviert, Bridge-Traffic wird nicht von der Firewall (iptables) verarbeitet, die IPv6-Autoconfiguration wird deaktiviert und Router Advertisements werden nicht ausgewertet.
Netzwerk
Externe Anbindung
Das Gateway in diesem Beispiel läuft als Virtuelle maschine auf einem Root-Server bei Hetzner unter KVM. Der Root-Server verfügt über ein zusätzliches Subnetz mit 8 IPv4-Adressen sowie ein IPv6-Subnetz. Um die wertvollen IPv4-Adressen alle nutzen zu können und diese nicht als Netzwerk- und Broadcast-Adresse "zu verbraten", wird eine etwas spezielle Netzwerk-Konfiguration verwendet:
modules="iproute2" # Natives IPv6-Netz (/64) v6net="2a01:4f8:210:5132" config_eth0="148.251.158.22 peer 148.251.152.51 ${v6net}:201::22/128" routes_eth0="default via 148.251.152.51 default via fe80::1" dns_domain="freifunk-gera-greiz.de" dns_servers="213.133.100.100 213.133.99.99 213.133.98.98"
Auf gw3 (Rootserver Kimsuf1 KS-2 SSD) sieht das so aus:
modules="iproute2" ############################### # Externe Anbindung ############################### config_eth0="5.196.74.176/24 2001:41d0:e:8b0::1/64" routes_eth0="default via 5.196.74.254 2001:41d0:e:8ff:ff:ff:ff:ff default via 2001:41d0:e:8ff:ff:ff:ff:ff" dns_domain="freifunk-gera-greiz.de" dns_servers="213.186.33.99 2001:41d0:3:163::1"
Bridge
Eine Bridge brauchen wir im Gateway nicht unbedingt. Sie erleichtert aber das Leben, da sie praktisch ohne Abhängigkeiten immer aktiv bleibt. Die Bridge erhält die Freifunk-internen IP-Adressen des Gateways, auch diese sind damit immer verfügbar. Daran können wir dann unsere internen Dienste (DNS, DHCP, NTP...) binden. Würden wir auf die Bridge verzichten, müßte das B.A.T.M.A.N.-Interface die IP-Adressen erhalten. Müßte dieses z.B. neu gestartet werden, müßten wir auch alle Dienste neu starten.Die Bridge wird in /etc/conf.d/net wie folgt konfiguriert:
############################### # Bridge ############################### # Dummy-Interface "ggrzDummy" für die Bridge "ggrzBR". Dieses Interface bekommt # die niedrigste Mac-Adresse aller Interfaces an der Bridge, welche dann auch # von der Bridge übernommen wird. tuntap_ggrzDummy="tap" config_ggrzDummy="null" rc_net_ggrzBR_need="net.ggrzDummy" bridge_ggrzBR="ggrzDummy" config_ggrzBR="10.181.0.11 netmask 255.255.192.0 brd 10.181.63.255 fdb5:078b:64cc::11/64" brctl_ggrzBR="setfd 0 sethello 10 stp off" routes_ggrzBR="10.181.0.0/18 proto kernel src 10.181.0.11 table ggrz fe80::/64 proto kernel table ggrz fdb5:078b:64cc::/64 proto kernel table ggrz 10.181.0.0/18 proto kernel src 10.181.0.11 table icvpn fe80::/64 proto kernel table icvpn fdb5:078b:64cc::/64 proto kernel table icvpn" rules_ggrzBR="iif ggrzBR table ggrz priority 1810" rules6_ggrzBR="iif ggrzBR table ggrz priority 1810" ############################### # Up-/Down-Scripts ############################### postup() { if $IFACE == ggrzDummy ; then /bin/ip link set address de:ad:be:ef:01:00 dev $IFACE elif $IFACE == ggrzBR ; then /bin/ip route add unreachable default table ggrz fi return 0 } predown() { if $IFACE == ggrzBR ; then /bin/ip route del unreachable default table ggrz fi return 0 }
Zuerst wird also ein Dummy-Interface angelegt, welches als erstes an die Bridge gebunden wird. Von diesem Interface übernimmt die Bridge die Mac-Adresse, welche im postup-Script gesetzt wird. In den Rules zur Bridge wird festgelegt, daß alle über die Bridge eingehenden Pakete über die Tabelle ggrz geroutet werden.
Da die zusätzlichen Routing-Tables nicht automatisch Device-Rpouten erhalten, werden diese in der Konfiguration hinzugefügt (routes_ggrzBR).
Die Interfaces werden nach Anlegen der erforderlichen Symlinks gestartet und in den Runlevel default aufgenommen:
# cd /etc/init.d # ln -s net.lo net.ggrzDummy # ln -s net.lo net.ggrzBR # rc-service net.ggrzDummy start # rc-service net.ggrzBR start # rc-update add net.ggrzDummy default # rc-update add net.ggrzBR default
GRETAP-Tunnel
Zwischen den Gateways werden GRETAP-Tunnel angelegt, worüber diese auf Layer2-Ebene verbunden werden. Die Tunnel werden in /etc/conf.d/net wie folgt konfiguriert:
############################### # Tunnel ############################### # ggrzTUN1: gw1 <-> gw2 # ggrzTUN2: gw1 <-> gw3 # ggrzTUN3: gw2 <-> gw3 config_ggrzTUN2="null" config_ggrzTUN3="null" ############################### # Up-/Down-Scripts ############################### preup() { if [...] elif $IFACE == ggrzTUN1 ; then /bin/ip link add $IFACE type gretap remote 193.28.153.11 local 148.251.158.22 key 1 /bin/ip link set address de:ad:be:ef:01:03 dev $IFACE elif $IFACE == ggrzTUN2 ; then /bin/ip link add $IFACE type gretap remote 5.196.74.176 local 148.251.158.22 key 2 /bin/ip link set address de:ad:be:ef:01:04 dev $IFACE fi return 0 } postdown() { if [...] elif $IFACE == ggrzTUN1 ; then /bin/ip link del $IFACE type gretap remote 193.28.153.11 local 148.251.158.22 key 1 elif $IFACE == ggrzTUN2 ; then /bin/ip link del $IFACE type gretap remote 5.196.74.176 local 148.251.158.22 key 2 fi return 0 }
Auch für diese Tunnel-Interfaces werden wieder Symlinks angelegt, sie werden gestartet und in den Default-Runlevel aufgenommen:
# cd /etc/init.d # ln -s net.lo net.ggrzTUN1 # ln -s net.lo net.ggrzTUN2 # rc-service net.TUN1 start # rc-service net.TUN2 start # rc-update add net.TUN1 default # rc-update add net.TUN2 default
B.A.T.M.A.N.
Als Kernel-Modul nutzen wir nicht das direkt im Kernel integrierte, da wir dort nicht dessen Version beeinflussen können. Zur Steuerung benötigen wir dann noch batctl:
# echo "net-misc/batman-adv-2015.1" >> /etc/portage/package.keywords/Freifunk # echo "net-misc/batctl-2015.1" >> /etc/portage/package.keywords/Freifunk # echo "net-misc/batman-adv bla dat debug mcast nc" >> /etc/portage/package.use/Freifunk # emerge -av batman-adv batctl
Die Konfiguration in /etc/conf.d/net:
############################### # Mesh-Interfaces ############################### config_ggrzBAT="null" rc_net_ggrzBAT_need="net.ggrzBR net.ggrzTUN1 net.ggrzTUN2" ############################### # Up-/Down-Scripts ############################### preup() { if $IFACE == ggrzBAT ; then /sbin/modprobe batman-adv /usr/sbin/batctl -m $IFACE if add ggrzTUN1 /usr/sbin/batctl -m $IFACE if add ggrzTUN2 /usr/sbin/batctl -m $IFACE gw server 96mbit/96mbit /usr/sbin/batctl -m $IFACE it 10000 /bin/ip link set address de:ad:be:ef:01:02 dev $IFACE echo 60 > /sys/class/net/$IFACE/mesh/hop_penalty /sbin/brctl addif ggrzBR $IFACE fi return 0 } postdown() { if $IFACE == ggrzBAT ; then /sbin/brctl delif ggrzBR $IFACE /usr/sbin/batctl -m $IFACE if del ggrzTUN1 /usr/sbin/batctl -m $IFACE if del ggrzTUN2 fi return 0 }
Das Mesh-Interface wird also nach Bridge- und GRETAP-Tunnels gestartet. Nach dem Start des Mesh-Interfaces werden die Tunnel ans Mesh-Interface gekoppelt und dieses in der Gateway-Mode versetzt. Anschließend wird das Mesh-Interface an die Bridge gehängt.
Der Start erfolgt wie gewohnt:
# cd /etc/init.d # ln -s net.lo net.ggrzBAT # rc-service net.BAT start # rc-update add net.BAT default
FastD
Der "Fast and secure tunneling Daemon" erstellt die Tunnel zwischen den Routern der Nodes und dem Gateway. Dafür gibt es keine fertigen Ebilds im Portage-Tree, aber sie sind bereits im Bugtracker gelandet: dev-libs/libuecc und net-misc/fastd. An diesen beiden Bugeinträgen hängen funktionierende Ebuilds, welche wir angepaßt und in unser Portage-Overlay integriert haben. Anschließend erfolgt die Installation mittels:
# echo "dev-libs/libuecc" >> /etc/portage/package.keywords/Freifunk # echo "net-misc/fastd" >> /etc/portage/package.keywords/Freifunk # echo "sys-devel/bison" >> /etc/portage/package.keywords/Freifunk # emerge -av fastd
Die Konfiguration für unsere Community Gera-Greiz wird in folgender Datei vorgenommen:
/etc/fastd/ggrz/fastd.conf
log to syslog level verbose; hide ip addresses yes; hide mac addresses yes; interface "ggrzVPN"; method "aes128-gcm"; method "salsa2012+umac"; method "null+salsa2012+umac"; # Bind auf externe v4 (genattet) and v6 Adressen bind 172.31.1.100:10181; bind [2a01:4f8:c17:229::12]:10181; mode tap; include "secret.conf"; mtu 1406; # 1492 - IPv4/IPv6 Header - fastd Header... include peers from "peers"; status socket "/var/run/fastd-gera-greiz.status"; on up " /bin/ip link set address de:ad:be:ef:03:01 dev $INTERFACE up /usr/sbin/batctl -m ggrzBAT if add $INTERFACE "; on down " /usr/sbin/batctl -m ggrzBAT if del $INTERFACE /bin/ip link set dev $INTERFACE down "; on verify " /etc/fastd/ggrz/fastd-blacklist.sh $PEER_KEY ";
Das "on verify" Script wird bei der Verbindungsaufnahme unbekannter Clients aufgerufen. Es hat folgenden Inhalt:
/etc/fastd/ggrz/fastd-blacklist.sh
#!/bin/bash if /bin/grep -Fq $PEER_KEY /etc/fastd/ggrz/fastd-blacklist.json; then exit 1 else exit 0 fi
Ist der Schlüssel des Clients in /etc/fastd/ggrz/fastd-blacklist.json aufgeführt, wird die Verbindung durch Rückgabe einer "1" abgewiesen, ansonsten werden Verbindungen unbekannter Knoten generell erlaubt (Rückgabe von "0").
Als nächstes werden die Keys erzeugt (die angezeigten Keys sind nur Beispiele):
# fastd --generate-key 2015-04-02 14:58:03 +0200 --- Info: Reading 32 bytes from /dev/random... Secret: 8897599cc0298ee31cff6e83315f68207b0c95cf03678da4b4b8b5661c9d1568 Public: 5818e1e0c322c2f414ec13b4ab536ac0696d571eebb0327ba2ce8beb5d159244
Der geheime Schlüssel wird wie folgt in secret.conf eingetragen, als Kommentar ist hier auch der zugehörige public Key hinterlegt:
/etc/fastd/ggrz/secret.conf
secret "8897599cc0298ee31cff6e83315f68207b0c95cf03678da4b4b8b5661c9d1568"; # # (public: a8fe6ec0e7d7a1bb125a02c06b8caa8b06405752667e346e85d81ee48f358109)
Der öffentliche Schlüssel muß dann noch in die site.conf zum Erstellen der Gluon-Firmware eingetragen werden, damit sich die Knoten-Router mit dem Gateway verbinden können.
Die öffentlichen Schlüssel der Knoten werden im Git-Repository "peers-ffggrz"eingetragen. Obwohl wir derzeit auch alle Verbindungen von unbekannten Knoten zulassen, geben wir die Knoten trotzdem unserem Gateway bekannt. So könnten wir ohne großen Aufwand bei Bedarf nur noch Verbindungen bekannter Knoten akzeptieren. Deswegen laden wir nun dieses Repository auf das Gateway:
# cd /etc/fastd/ggrz # git clone https://github.com/ffggrz/peers-ffggrz.git peers
Mit dem folgenden Script wird dafür gesorgt, daß die Peers aktuell bleiben:
/etc/fastd/update-fastd-peers
# fastd configuration directory FASTD_CFG=/etc/fastd # FF Communities COMMUNITIES="ggrz" function getCurrentVersion() { # Get hash from latest revision git log --format=format:%H -1 } cd $FASTD_CFG/$COMMUNITIES/peers # Get current version hash GIT_REVISION=$(getCurrentVersion) # Automagically commit local changes # This preserves local changes git commit -m "CRON: auto commit" # Pull latest changes from upstream git fetch git merge origin/master -m "Auto Merge" # Get new version hash GIT_NEW_REVISION=$(getCurrentVersion) if [ $GIT_REVISION != $GIT_NEW_REVISION ] then # Reload updated configuration echo "Reload fastd configuration." kill -HUP $(pidof fastd.$COMMUNITIES) fi
Das Script muß ausführbar sein:
# chmod 750 /etc/fastd/update-fastd-peers
Nun muß dieses Script noch regelmäßig per Cron aufgerufen werden:
/etc/cron.d/update-fastd-peers
# Global variables SHELL=/bin/bash PATH=/sbin:/bin:/usr/sbin:/usr/bin MAILTO=root HOME=/ # Update fastd peers every 15 minutes. */15 * * * * root /etc/fastd/update-fastd-peers > /dev/null
Zuletzt legen wir noch einen Symlink des Startscriptes für die FastD-Instanz der Community an, starten diese und nehmen sie in den Default-Runlevel auf:
# cd /etc/init.d # ln -s fastd /etc/init.d/fastd.ggrz # rc-service fastd.ggrz start # rc-update add fastd.ggrz default
Exit-VPN
Zur Vermeidung der Störerhaftungs-Problematik erfolgt der Internet-Zugang ausschließlich per VPN über einen Server im Ausland oder den Server eines Vereines mit Provider-Status. In den meisten Fällen wird dabei ein Tunnel mit OpenVPN aufgebaut. Das installieren wir deswegen:
# echo "net-misc/openvpn iproute2 passwordsave" >> /etc/portage/package.use/Freifunk # emerge -av openvpn
In /etc/conf.d/openvpn muß die Zeile PEER_DNS="yes" ersetzt werden durch PEER_DNS="no".
Oft erhält man vom VPN-Anbieter eine fertige Konfiguration, diese wird nach /etc/openvpn/
Für Mullvad sieht die Konfiguration z.B. so aus:
/etc/openvpn/mullvad.conf
client remote se.mullvad.net 1300 ##remote nl.mullvad.net 1300 cipher AES-256-CBC dev exitVPN dev-type tun proto udp tun-ipv6 resolv-retry infinite route-noexec persist-key persist-tun nobind ping 5 ping-restart 60 ping-timer-rem explicit-exit-notify 2 script-security 2 remote-cert-tls server route-delay 5 ##tun-mtu 1500 ##fragment 1300 ##mssfix 1300 verb 4 comp-lzo ca /etc/openvpn/mullvad/ca.crt cert /etc/openvpn/mullvad/mullvad.crt key /etc/openvpn/mullvad/mullvad.key crl-verify /etc/openvpn/mullvad/crl.pem # Limit range of possible TLS cipher-suites tls-cipher TLS-DHE-RSA-WITH-AES-256-CBC-SHA:TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA:TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA:TLS-DHE-RSA-WITH-AES-128-CBC-SHA:TLS-DHE-RSA-WITH-SEED-CBC-SHA:TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SH
Das CA-Zertifikat von Mullvad, das eigene Zertifikat und der zugehörige private key sowie die CRL gehören also nach /etc/openvpn/mullvad.
Weiterhin benötigen wir Up- und Down-Scripte, in denen Routen und Regeln gesetzt werden:
/etc/openvpn/openvpn.mullvad-up.sh
#!/bin/sh # ip rules for maintenance ip rule add from $ifconfig_local table ggrz priority 9181 # ipv4 default route into appropriate rt_table ip route replace 0.0.0.0/1 via $route_vpn_gateway dev $dev table ggrz ip route replace 128.0.0.0/1 via $route_vpn_gateway dev $dev table ggrz # ipv6 default route into appropriate rt_table ip -6 route replace 2000::/3 dev $dev table ggrz exit 0
/etc/openvpn/openvpn.mullvad-down.sh
#!/bin/sh # ip rules for maintenance ip rule del from $ifconfig_local table ggrz priority 9181
Zuletzt wird wieder ein Symlink für den Initscript erstellt, dieser gestartet und in den Default-Runlevel aufgenommen:
# nano -w /etc/openvpn/.conf # cd /etc/init.d # ln -s openvpn /etc/init.d/openvpn. # rc-service openvpn. start # rc-update add openvpn. default
IC-VPN
Installation
# echo "net-misc/bird" >> /etc/portage/package.keywords/Freifunk # echo "net-misc/tinc" >> /etc/portage/package.keywords/Freifunk # emerge -av bird tinc
tinc
Wesentliche Community-übergreifende Konfigurationen liegen in einem Git-Repository, welches wir klonen:
# mkdir /etc/tinc/icVPN # git clone https://github.com/freifunk/icvpn /etc/tinc/icVPN/
Zur Absicherung des Tunnels wird ein Schlüsselpaar erzeugt:
# tincd -n icvpn -K
Bei den Vorgaben für den Speicherort wird der Verzeichnisname icvpn durch icVPN ersetzt. Also /etc/tinc/icVPN/rsa_key.priv und /etc/tinc/icVPN/rsa_key.pub.
Anschließend erstellen wir den Kopf der Konfiguration von tinc:
/etc/tinc/icVPN/tinc.conf.header:
Name = gera_greiz1 PrivateKeyFile = /etc/tinc/icVPN/rsa_key.priv Mode = Switch PingTimeout = 30 Port = 10781 Hostnames = yes Interface = icVPN
Diesen Header kopieren wir in die eigentliche tinc-Konfiguration:
# cp /etc/tinc/icVPN/tinc.conf.header /etc/tinc/icVPN/tinc.conf
Nun benötigen wir Scripts zur Netzwerk-Konfiguration, welches tinc nach dem Verbindungsauf- und -abbau ausführt:
/etc/tinc/icVPN/tinc-up:
#!/bin/sh # Interface aktivieren und IP-Adressen setzen /bin/ip link set dev $INTERFACE up /bin/ip addr add dev $INTERFACE 10.207.0.181/16 broadcast 10.207.255.255 scope link /bin/ip -6 addr add dev $INTERFACE fec0::a:cf:0:b5/96 preferred_lft 0 # Device-Routen in den anderen Routing-Tabellen /bin/ip -4 route add 10.207.0.0/16 proto kernel dev $INTERFACE src 10.207.0.181 table ggrz /bin/ip -6 route add fec0::a:cf:0:0/96 proto kernel dev $INTERFACE table ggrz /bin/ip -6 route add fe80::/64 proto kernel dev $INTERFACE table ggrz /bin/ip -4 route add 10.207.0.0/16 proto kernel dev $INTERFACE src 10.207.0.181 table icvpn /bin/ip -6 route add fec0::a:cf:0:0/96 proto kernel dev $INTERFACE table icvpn /bin/ip -6 route add fe80::/64 proto kernel dev $INTERFACE table icvpn ### Default-Route zu vpn03 Berlin ##ip route replace 0.0.0.0/1 via 10.207.0.6 dev $INTERFACE table ggrz ##ip route replace 128.0.0.0/1 via 10.207.0.6 dev $INTERFACE table ggrz # ip rules /bin/ip rule add priority 31000 iif $INTERFACE table icvpn /bin/ip rule add priority 31001 iif $INTERFACE unreachable /bin/ip -6 rule add priority 31000 iif $INTERFACE table icvpn /bin/ip -6 rule add priority 31001 iif $INTERFACE unreachable
/etc/tinc/icVPN/tinc-down:
#!/bin/sh /bin/ip addr del dev $INTERFACE 10.207.0.181/16 broadcast 10.207.255.255 /bin/ip -6 addr del dev $INTERFACE fec0::a:cf:0:b5/96 # ip rules /bin/ip rule del priority 31000 iif $INTERFACE table icvpn /bin/ip rule del priority 31001 iif $INTERFACE unreachable /bin/ip -6 rule del priority 31000 iif $INTERFACE table icvpn /bin/ip -6 rule del priority 31001 iif $INTERFACE unreachable # shutdown interface /bin/ip link set dev $INTERFACE down
Beide Scripts müssen ausführbar sein:
# chmod 755 /etc/tinc/icVPN/tinc-*
Nun wird noch ein Script benötigt, welches die Konfiguration um die aktuellen Peer-Einträge ergänzt:
/etc/tinc/icVPN/update-tincd-icvpn:
#!/bin/bash # Simple script for update of tinc IC-VPN hosts from git # upstream and automated creation of tincd configuration. # Tinc IC-VPN configuration directory TINC_ICVPN=/etc/tinc/icVPN # IC-VPN configuration file TINC_CONF=tinc.conf # IC-VPN configuration file header TINC_CONF_HEADER=tinc.conf.header # IC-VPN host file directory TINC_HOSTS=hosts function getCurrentVersion() { # Get hash from latest revision git log --format=format:%H -1 } cd $TINC_ICVPN # Get current version hash GIT_REVISION=$(getCurrentVersion) # Automagically commit local changes # This preserves local changes git commit -m "CRON: auto commit" # Pull latest changes from upstream git fetch git merge origin/master -m "Auto Merge" # Get new version hash GIT_NEW_REVISION=$(getCurrentVersion) if [ $GIT_REVISION != $GIT_NEW_REVISION ] then # Start with header file for tinc configuration cp $TINC_CONF_HEADER $TINC_CONF # Iterate through hosts in metanodes while read HOST; do # search correspondending host with address grep -iq '^Address' -- hosts/"$HOST" || continue # Add ConnectTo line for current host echo "ConnectTo = $HOST" >> $TINC_CONF done < metanodes # Reload updated configuration echo "Reload tincd configuration." kill -HUP $(pidof tincd) fi
Auch dieses Script muß ausführbar sein:
# chmod 750 /etc/tinc/icVPN/update-tincd-icvpn
Um dann stündlich abgearbeitet zu werden, legen wir für cron folgende Datei an:
/etc/cron.d/update-tincd-icvpn
# Global variables SHELL=/bin/bash PATH=/sbin:/bin:/usr/sbin:/usr/bin MAILTO=root HOME=/ # Update tincd IC-VPN peers every hour. 42 * * * * root /etc/tinc/icVPN/update-tincd-icvpn > /dev/null
Wichtig sind die richtigen Berechtigungen und ein Neustart von Cron:
# chmod 644 /etc/cron.d/update-tincd-icvpn # /etc/init.d/vixie-cron restart
Nun müssen wir unser Gateway im Git hinterlegen und damit den anderen Gateways bekanntgeben. Dazu wird ein Push-Request auf https://github.com/freifunk/icvpn mit folgender Datei im Verzeichnis hosts erstellt:
gera_greiz1:
Address = gw1.freifunk-gera-greiz.de Port = 10781 -----BEGIN RSA PUBLIC KEY----- MIIBCgKCAQEArLhMleQyfCgADO1vPEHK1hTJ8ZW/NljeiFsZcvTHCRKnnfF0AP1S XfcviGlQCV3sfhXLdKABe0QZiLeHwbJY2R/n0PJxG/UxfscAKH+vRCa6qA4PqVI7 CLShMe+E/S66UPvYzYYwBpfLBFYlaMzSz+IhvhiRwoCWgk/0+YfPJt85mFSUHNxN XGiBLJBSRGnGi9BFSw+GbrN86lmknV/fnL4uypFw94TJYF0Q7TexgP7aRtFSOciH 2tDCbzzJh7lmw4XE1Wtz7QWUP/R34zqlOELXlmoilbkTO71y4qlCeTHmaWDOG9/f VScV3K/v1mrofNlK35GJzfcOp9ueijIbZwIDAQAB -----END RSA PUBLIC KEY-----
Der public Key ist der Inhalt von /etc/tinc/icVPN/rsa_key.pub.
Zum Abschluß wird tinc gestartet:
# cd /etc/init.d # ln -s tincd /etc/init.d/tincd.icVPN # rc-service tincd.icVPN start # rc-config add tincd.icVPN default
Nun können wir noch kontrollieren, ob alles wie gewünscht funktioniert. Das Interface:
# ifconfig icVPN icVPN: flags=4163mtu 1500 inet 10.207.0.181 netmask 255.255.0.0 broadcast 10.207.255.255 inet6 fe80::3001:89ff:fe38:e613 prefixlen 64 scopeid 0x20 inet6 fec0::a:cf:0:b5 prefixlen 96 scopeid 0x40 ether 32:01:89:38:e6:13 txqueuelen 500 (Ethernet) RX packets 49766 bytes 2922522 (2.7 MiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 749 bytes 50702 (49.5 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
Erreichbarbeit anderer Peers, z.B. berlin2:
# ping -c2 10.207.0.6 PING 10.207.0.6 (10.207.0.6) 56(84) bytes of data. 64 bytes from 10.207.0.6: icmp_seq=1 ttl=64 time=1.53 ms 64 bytes from 10.207.0.6: icmp_seq=2 ttl=64 time=1.17 ms --- 10.207.0.130 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1001ms rtt min/avg/max/mdev = 1.171/1.354/1.537/0.183 ms # ping6 -c2 fec0::a:cf:0:6 PING fec0::a:cf:0:6(fec0::a:cf:0:6) 56 data bytes 64 bytes from fec0::a:cf:0:6: icmp_seq=1 ttl=64 time=1.10 ms 64 bytes from fec0::a:cf:0:6: icmp_seq=2 ttl=64 time=2.20 ms --- fec0::a:cf:0:82 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1001ms rtt min/avg/max/mdev = 1.108/1.656/2.204/0.548 ms
bird
# mkdir /etc/bird # mkdir /etc/bird/bird.d # mkdir /etc/bird/bird6.d # touch /etc/bird/bird.conf # touch /etc/bird/bird6.conf # ln -s bird/bird.conf /etc/bird.conf # ln -s bird/bird6.conf /etc/bird6.conf
Nun erstellen bzw. editieren wir folgende Konfigurations-Dateien:
/etc/bird/local.conf:
# lokale Parameter (verschieden für jedes Gateway unserer Community) router id 10.207.0.181; # Router-Id (entspricht üblicherweise v4-IP-Adresse) define addr_ic = 10.207.0.181; # eigene Gateway-Adresse im IC-VPN (Tinc-Tunnel) define addr_br = 10.181.0.11; # eigene Mesh-Bridge-IP define addr_neighbor1 = 10.181.0.12; # interner Peer 1 define addr_neighbor2 = 10.181.0.13; # interner Peer 2
/etc/bird/bird.conf:
timeformat protocol iso long; # lokale Konfigurationsdaten einbinden include "/etc/bird/local.conf"; # AS define ggrz_as = 65181; # AS Gera-Greiz # Bird Routingtabellen table ggrz; # internes Mesh table icvpn; # ICVPN # ROA roa table roa_icvpn { include "/etc/bird/bird.d/icvpn-roa"; } ##################### ### F U N C T I O N S ##################### # # alle Freifunk-Netze function is_freifunk() { return net ~ [ 10.0.0.0/8+ ]; } # alle DN42-Netze function is_dn42() { return net ~ [ 172.20.0.0/16+, 172.22.0.0/15+ ]; } # alle Chaos-VPN-Netze function is_chaosvpn() { return net ~ [ 172.31.0.0/16+ ]; } # Mesh-Netze Gera-Greiz function is_ggrz_self_net() { return net ~ [ 10.181.0.0/16+ ]; } ##################### ### F I L T E R S ##################### # # Import-Filter für alle ICVPN-Peers filter ebgp_icvpn_import_filter { if is_ggrz_self_net() then reject; # eigene Netze zurückweisen if is_freifunk() then accept; # interne Freifunk-Netze erlauben if is_dn42() then accept; # DN42-Netze erlauben if is_chaosvpn() then accept; # CaosVPN-Netze erlauben # if roa_check(roa_icvpn) = ROA_VALID then { # Test Route Origin Authorization für Freifunk-Netze # accept; # } else { # print "ROA check failed for ", net, " ASN ", bgp_path.last; # } reject; # alles andere ablehnen } ##################### ### P R O T O C O L S ##################### # # Interfaces abfragen protocol device { scan time 30; }; # Device-Routen in Bird-Table icvpn aufnehmen protocol direct ggrz_subnets { interface 10.181.0.0/16; table icvpn; }; # Bird-Tabelle ICVPN nach GGRZ kopieren protocol pipe icvpn2ggrz { import none; # nichts von ggrz nach icvpn importieren export all; # alles von icvpn nach ggrz exportieren table icvpn; # Quelle: icvpn peer table ggrz; # Ziel: ggrz }; # Kernel-Routing-Table fürs Mesh-Netz Gera-Greiz protocol kernel kernel_ggrz { scan time 30; import none; # nichts von Kernel in Bird importieren export filter { if is_ggrz_self_net() then # eigene Netze nicht zum Kernel exportieren reject; krt_prefsrc = addr_br; accept; # alles andere Bird-ggrz-Tabelle kommt in Kernel }; table ggrz; # Bird-Tabelle icvpn kernel table 181; # Kernel-Tabelle icvpn (s. etc/iproute2/rt_tables) }; # Kernel-Routing-Table fürs IC-VPN protocol kernel kernel_icvpn { scan time 30; import none; # nichts von Kernel in Bird importieren export filter { if is_ggrz_self_net() then # eigene Netze nicht zum Kernel exportieren reject; krt_prefsrc = addr_ic; accept; # alles andere vom IC-VPN kommt in Kernel }; table icvpn; # Bird-Tabelle icvpn kernel table 42; # Kernel-Tabelle icvpn (s. etc/iproute2/rt_tables) }; ##################### ### T E M P L A T E S ##################### # # Template für iBGP (interne Peers) template bgp ibgp { local addr_br as ggrz_as; # als eigene IP die der Mesh-Bridge verwenden table icvpn; # Bird-Tabelle icvpn (korrekt???) import keep filtered on; # gefilterte Routen nicht löschen, # sondern verstecken und nicht propagieren # können dadurch mit "show route filtered" angesehen werden import all; # EXPERIMENT !!!!! export where source = RTS_BGP; # alles, was über BGP hereingekommen ist, exportieren direct; # Nachbar ist direkt verbunden gateway direct; # Next Hop wird nicht durch Lookup der Routing Table ermittelt, # sondern der bgp_next_hop genommen (falls direkt erreichbar, # sonst die Adresse des Neighbor }; # Template für eBGP (Peers im IC-VPN) template bgp peers { local addr_ic as ggrz_as; # als eigene IP die des Tinc-Tunnels verwenden table icvpn; # Bird-Tabelle icvpn import keep filtered on; # gefilterte Routen nicht löschen, # sondern verstecken und nicht propagieren # können dadurch mit "show route filtered" angesehen werden import filter ebgp_icvpn_import_filter; export filter { if is_ggrz_self_net() then { # interne Netze Gera-Greiz accept; # exportieren } if source = RTS_BGP then { # wenn über BGP gelernt und if is_freifunk() || is_dn42() || is_chaosvpn() then { # wenn es sich um ein Freifunk-, DN42- oder Chaos-Netz handelt accept; # exportieren } } reject; # alle anderen Routen nicht exportieren }; direct; # Nachbar ist direkt verbunden }; ##################### ### P E E R I N G S ##################### # # iBGP (interne Peers) ##protocol bgp neighbor1 from ibgp { ## neighbor addr_neighbor1 as ggrz_as; ##}; ##protocol bgp neighbor2 from ibgp { ## neighbor addr_neighbor2 as ggrz_as; ##}; # eBGP IC-VPN Peers # erzeugt mit /etc/cron.d/update-icvpn-meta # ruft auf: /etc/icvpn/update-icvpn-meta # Parameter BIRD_TEMPLATE muß dem Templatenamen (peers) entsprechen include "/etc/bird/bird.d/icvpn";
/etc/bird/local6.conf
# lokale Parameter (verschieden für jedes Gateway unserer Community) router id 10.207.0.183; # Router-Id (entspricht üblicherweise v4-IP-Adresse) define addr_ic = fec0::a:cf:0:b5; # eigene Gateway-Adresse im IC-VPN (Tinc-Tunnel) define addr_br = fdb5:78b:64cc::11; # eigene Mesh-Bridge-IP define addr_neighbor1 = fdb5:78b:64cc::12; # interner Peer 1 define addr_neighbor2 = fdb5:78b:64cc::13; # interner Peer 2
/etc/bird/bird6.conf
timeformat protocol iso long; # lokale Konfigurationsdaten einbinden include "/etc/bird/local6.conf"; # AS define ggrz_as = 65181; # AS Gera-Greiz # Bird Routingtabellen table ggrz; # internes Mesh table icvpn; # ICVPN # ROA roa table roa_icvpn { include "/etc/bird/bird6.d/icvpn-roa"; } ##################### ### F U N C T I O N S ##################### # # ULA Adressen function is_ula() { return net ~ [ fc00::/7{48,64} ]; } # Mesh-Netze Gera-Greiz function is_ggrz_self_net() { return net ~ [ fdb5:078b:64cc::/48+ ]; } ##################### ### F I L T E R S ##################### # # Import-Filter für alle ICVPN-Peers filter ebgp_icvpn_import_filter { if is_ggrz_self_net() then reject; # eigene Netze zurückweisen if is_ula() then accept; # Netze mit ULA-Adressen erlauben # if roa_check(roa_icvpn) = ROA_VALID then { # Test Route Origin Authorization für Freifunk-Netze # accept; # } else { # print "ROA check failed for ", net, " ASN ", bgp_path.last; # } reject; # alles andere ablehnen } ##################### ### P R O T O C O L S ##################### # # Interfaces abfragen protocol device { scan time 30; }; # Device-Routen in Bird-Table icvpn aufnehmen protocol direct ggrz_subnets { interface fdb5:078b:64cc::/48; table icvpn; }; # Bird-Tabelle ICVPN nach GGRZ kopieren protocol pipe icvpn2ggrz { import none; # nichts von ggrz nach icvpn importieren export all; # alles von icvpn nach ggrz exportieren table icvpn; # Quelle: icvpn peer table ggrz; # Ziel: ggrz }; # Kernel-Routing-Table fürs Mesh-Netz Gera-Greiz protocol kernel kernel_ggrz { scan time 30; import none; # nichts von Kernel in Bird importieren export filter { if is_ggrz_self_net() then # eigene Netze nicht zum Kernel exportieren reject; krt_prefsrc = addr_br; accept; # alles andere Bird-ggrz-Tabelle kommt in Kernel }; table ggrz; # Bird-Tabelle icvpn kernel table 181; # Kernel-Tabelle icvpn (s. etc/iproute2/rt_tables) }; # Kernel-Routing-Table fürs IC-VPN protocol kernel kernel_icvpn { scan time 30; import none; # nichts von Kernel in Bird importieren export filter { if is_ggrz_self_net() then # eigene Netze nicht zum Kernel exportieren reject; krt_prefsrc = addr_ic; accept; # alles andere vom IC-VPN kommt in Kernel }; table icvpn; # Bird-Tabelle icvpn kernel table 42; # Kernel-Tabelle icvpn (s. etc/iproute2/rt_tables) }; ##################### ### T E M P L A T E S ##################### # # Template für iBGP (interne Peers) template bgp ibgp { local addr_br as ggrz_as; # als eigene IP die der Mesh-Bridge verwenden table icvpn; # Bird-Tabelle icvpn (korrekt???) import keep filtered on; # gefilterte Routen nicht löschen, # sondern verstecken und nicht propagieren # können dadurch mit "show route filtered" angesehen werden import all; # EXPERIMENT !!!!! export where source = RTS_BGP; # alles, was über BGP hereingekommen ist, exportieren direct; # Nachbar ist direkt verbunden gateway direct; # Next Hop wird nicht durch Lookup der Routing Table ermittelt, # sondern der bgp_next_hop genommen (falls direkt erreichbar, # sonst die Adresse des Neighbor }; # Template für eBGP (Peers im IC-VPN) template bgp peers { local addr_ic as ggrz_as; # als eigene IP die des Tinc-Tunnels verwenden table icvpn; # Bird-Tabelle icvpn import keep filtered on; # gefilterte Routen nicht löschen, # sondern verstecken und nicht propagieren # können dadurch mit "show route filtered" angesehen werden import filter ebgp_icvpn_import_filter; export filter { if is_ggrz_self_net() then { # interne Netze Gera-Greiz accept; # exportieren } if source = RTS_BGP then { # wenn über BGP gelernt und if is_ula() then { # wenn es sich um Netze mit ULA-Adressen handelt accept; # exportieren } } reject; # alle anderen Routen nicht exportieren }; direct; # Nachbar ist direkt verbunden }; ##################### ### P E E R I N G S ##################### # # iBGP (interne Peers) ##protocol bgp neighbor1 from ibgp { ## neighbor addr_neighbor1 as ggrz_as; ##}; ##protocol bgp neighbor2 from ibgp { ## neighbor addr_neighbor2 as ggrz_as; ##}; # eBGP IC-VPN Peers # erzeugt mit /etc/cron.d/update-icvpn-meta # ruft auf: /etc/icvpn/update-icvpn-meta # Parameter BIRD_TEMPLATE muß dem Templatenamen (peers) entsprechen include "/etc/bird/bird6.d/icvpn";
Der Austauch der Konfirurationsparameter der einzelnen Communities geschieht wieder per Git. Es gibt ein Repository mit den Daten (icvpn-meta) und eines mit Scripts zur Erzeugung der Konfigurationen (icvpn-scripts). Für die Scripts wird python-yaml benötigt. Das installieren wir, anschließend clonen wir die beiden Repositories:
# emerge -av pyyaml # mkdir /etc/icvpn # cd /etc/icvpn # git clone https://github.com/freifunk/icvpn-meta.git meta # git clone https://github.com/freifunk/icvpn-scripts.git scripts
Unsere eigene Community müssen wir auch bekanntgeben. Dazu wird ein Push-Request auf https://github.com/freifunk/icvpn-meta mit folgender Datei erstellt:
gera-greiz:
tech-c: -Diese E-Mail-Adresse ist vor Spambots geschützt! Zur Anzeige muss JavaScript eingeschaltet sein. asn: 65181 networks: ipv4: - 10.181.0.0/16 ipv6: - fdb5:078b:64cc::/48 bgp: gera_greiz1: ipv4: 10.207.0.181 ipv6: fec0::a:cf:0:b5 domains: - ffggrz - 181.10.in-addr.arpa - c.c.4.6.b.8.7.0.5.b.d.f.ip6.arpa nameservers: - 10.181.0.11 - fdb5:78b:64cc::11
Jetzt benötigen wir ein Script, welches das lokale Git-Repository aktualisiert und daraus die Konfigurationen für bird und dnsmasq erzeugt:
/etc/icvpn/update-icvpn-meta:
****!/bin/bash # Simple script for update of IC-VPN meta information from git upstream # and automated creation of derived bird and dnsmasq configuration. # Note that scripts are not automatically updated for security reasons. # Local icvpn-meta and icvpn-script clones ICVPN_META=/etc/icvpn/meta ICVPN_SCRIPTS=/etc/icvpn/scripts # Name of own community (as used in icvpn-meta repository) OWN_COMMUNITY=gera-greiz # Bird peer configuration (IPv4 and IPv6) BIRD_CONF=/etc/bird/bird.d/icvpn BIRD6_CONF=/etc/bird/bird6.d/icvpn # Bird roa configuration (IPv4 and IPv6) BIRD_ROA=/etc/bird/bird.d/icvpn-roa BIRD6_ROA=/etc/bird/bird6.d/icvpn-roa BIRD_ROA_LEN=24 BIRD6_ROA_LEN=64 # Bird templates used for peers (IPv4 and IPv6) BIRD_TEMPLATE=peers BIRD6_TEMPLATE=peers # Dnsmasq configuration DNSMASQ_CONF=/etc/dnsmasq.d/icvpn function getCurrentVersion() { # Get hash from latest revision git log --format=format:%H -1 } cd $ICVPN_META # Get current version hash GIT_REVISION=$(getCurrentVersion) # Automagically commit local changes # This preserves local changes git commit -m "CRON: auto commit" # Pull latest changes from upstream git fetch git merge origin/master -m "Auto Merge" # Get new version hash GIT_NEW_REVISION=$(getCurrentVersion) # Check whether content of icvpn-meta has changed if [ $GIT_REVISION != $GIT_NEW_REVISION ] then cd $ICVPN_SCRIPTS # Create bird configuration ./mkbgp -4 -f bird -s $ICVPN_META -d $BIRD_TEMPLATE -x $OWN_COMMUNITY > $BIRD_CONF ./mkbgp -6 -f bird -s $ICVPN_META -d $BIRD6_TEMPLATE -x $OWN_COMMUNITY > $BIRD6_CONF ./mkroa -4 -f bird -s $ICVPN_META -m $BIRD_ROA_LEN -x $OWN_COMMUNITY > $BIRD_ROA ./mkroa -6 -f bird -s $ICVPN_META -m $BIRD6_ROA_LEN -x $OWN_COMMUNITY > $BIRD6_ROA # Restrict access ##chown bird.bird $BIRD_CONF $BIRD6_CONF $BIRD_ROA $BIRD6_ROA chmod 640 $BIRD_CONF $BIRD6_CONF $BIRD_ROA $BIRD6_ROA # Create dnsmasq configuration ./mkdns -f dnsmasq -s $ICVPN_META -x OWN_COMMUNITY > $DNSMASQ_CONF # Version has changed we need to update echo "Reload bird configuration." kill -HUP $(pidof bird) kill -HUP $(pidof bird6) echo "Reload dnsmasq configuration." /sbin/rc-service dnsmasq restart fi
Die Programme zum Erstellen der Bird- und Dnsmasq-Konfiguration benötigen ein Python 2.x, kein 3.x. Ansonsten bleiben beim Aufruf per Cron (warum auch immer?) die erzeugten Konfigurationen leer. Deswegen wird Python 2.7 als System-Python eingestellt (mittels "eselect python set x").
Das Script sollte ausführbar sein:
# chmod 750 /etc/icvpn/update-icvpn-meta
Um dann stündlich abgearbeitet zu werden, legen wir für cron folgende Datei an:
/etc/cron.d/update-icvpn-meta
# Global variables SHELL=/bin/bash PATH=/sbin:/bin:/usr/sbin:/usr/bin MAILTO=root HOME=/ # Update tincd IC-VPN peers every hour. 37 * * * * root /etc/icvpn/update-icvpn-meta > /dev/null
Die Cron-Datei muß die richtigen Rechte bekommen und Cron neu gestartet werden:
# chmod 644 /etc/cron.d/update-icvpn-meta # /etc/init.d/vixie-cron restart
ZumSchluß wird bird gestartet und in den Default-Runlevel aufgenommen:
# /etc/init.d/bird start # /etc/init.d/bird6 start # rc-update add bird default # rc-update add bird6 default
Zur Kontrolle werden die Routing-Tabellen angezeigt, diese müssen jede Menge Einträge enthalten:
# ip route show table icvpn [...] # ip route show table ggrz [...] # ip -6 route show table icvpn [...] # ip -6 route show table ggrz [...]
Ein paar weitere Tests:
Eine Schwierigkeit ist die Ermittlung eines möglichen Ping-Ziels im ICVPN. Am wahrsccheinlichsten ist es, daß man einen der DNS-Server anderer Communities erreichen kann. Diese kann man wie folgt auflisten:
# cat /etc/dnsmasq.d/icvpn
In den folgenden Beispielen nutzen wir die 10.56.0.7.
Diese sollte man dann von einem Client aus unserem Freifunk-Netz anpingen können. Für einen Test direkt vom Gateway muß man mit einer "ip rule" noch dafür sorgen, daß wie für die Clients die Routing-Table "ggrz" verwendet wird:
# ip rule add to 10.56.0.7 table ggrz priority 32000 # ping 10.56.0.7 # ip rule del to 10.56.0.7 table ggrz priority 32000
Das korrekte Routing kann auch schneller wir folgt getestet werden:
# ip route get to 10.56.0.7 from 10.181.0.22 iif ggrzBAT 10.56.0.7 from 10.181.0.22 via 10.207.0.56 dev icVPN cache iif ggrzBAT
Backbone Rheinland
Gre-Tunnel
Der Freifunk Rheinland e.V. ermöglicht uns den Exit ins Internet. Dazu werden GRE-Tunnel zu den dortigen Gateways erstellt. Die Konfiguration in /etc/conf.d/net:
############################### # Tunnel ############################### # ffrl-a-ak-ber: Backbone Rheinland (A), Berlin # ffrl-a-ix-dus: Backbone Rheinland (A), Düsseldorf # ffrl-b-ak-ber: Backbone Rheinland (B), Berlin # ffrl-b-ix-dus: Backbone Rheinland (B), Düsseldorf # iptunnel_ffrl_a_ak_ber="mode gre local 148.251.158.22 remote 185.66.195.0 ttl 64" config_ffrl_a_ak_ber="100.64.3.167 peer 100.64.3.166 185.66.194.27/32 2a03:2260:0:1dd::2/64" mtu_ffrl_a_ak_ber="1400" # iptunnel_ffrl_a_ix_dus="mode gre local 148.251.158.22 remote 185.66.193.0 ttl 64" config_ffrl_a_ix_dus="100.64.3.169 peer 100.64.3.168 185.66.194.27/32 2a03:2260:0:1de::2/64" mtu_ffrl_a_ix_dus="1400" # iptunnel_ffrl_b_ak_ber="mode gre local 148.251.158.22 remote 185.66.195.1 ttl 64" config_ffrl_b_ak_ber="100.64.3.171 peer 100.64.3.170 185.66.194.27/32 2a03:2260:0:1df::2/64" mtu_ffrl_b_ak_ber="1400" # iptunnel_ffrl_b_ix_dus="mode gre local 148.251.158.22 remote 185.66.193.1 ttl 64" config_ffrl_b_ix_dus="100.64.3.173 peer 100.64.3.172 185.66.194.27/32 2a03:2260:0:1e0::2/64" mtu_ffrl_b_ix_dus="1400"
Danach werden die Symlinks der Init-Scripts der einzelnen Interfaces erstellt, die Tunnel gestartet und in den Default-Runlevel aufgenommen:
# cd /etc/init.d # ln -s net.lo net.ffrl-a-ak-ber # ln -s net.lo net.ffrl-a-ix-dus # ln -s net.lo net.ffrl-b-ak-ber # ln -s net.lo net.ffrl-b-ix-dus # rc-service net.ffrl-a-ak-ber start # rc-service net.ffrl-a-ix-dus start # rc-service net.ffrl-b-ak-ber start # rc-service net.ffrl-b-ix-dus start # rc-update add net.ffrl-a-ak-ber default # rc-update add net.ffrl-a-ix-dus default # rc-update add net.ffrl-b-ak-ber default # rc-update add net.ffrl-b-ix-dus default
Firewall
Layer 3
Primär dient die Firewall an dieser Stelle dazu, die Pakete aus der Freifunk-Mesh Richtung Exit-VPN zu natten und zu markieren, um sie an die spezielle Routing-Tabelle (181, ggrz) zu übergeben. Dazu legen wir die folgenden Regeln an:
IPv4:
# iptables -t filter -A INPUT -i eth0 -p tcp --dport 179 -j REJECT # iptables -t filter -A INPUT -i exitVPN -p tcp --dport 179 -j REJECT # iptables -t filter -A INPUT -i ggrzBR -p tcp --dport 179 -j REJECT # iptables -A FORWARD -i ggrzBR -o eth0 -p tcp --dport 587 -m connlimit --connlimit-above 5 -j REJECT # iptables -t mangle -A PREROUTING -i ggrzBR -j MARK --set-xmark 0x1/0xffffffff # iptables -t mangle -A PREROUTING -i ggrzBR -p tcp --dport 587 -j MARK --set-mark 0x0/0xffffffff # iptables -t nat -A POSTROUTING -o exitVPN -j MASQUERADE # iptables -t nat -A POSTROUTING -o eth0 -p tcp --dport 587 -j MASQUERADE # iptables -t nat -N ffrl-nat # iptables -t nat -A ffrl-nat -s 100.64.3.166/31 -o ffrl+ -j RETURN # iptables -t nat -A ffrl-nat -s 100.64.3.168/31 -o ffrl+ -j RETURN # iptables -t nat -A ffrl-nat -s 100.64.3.170/31 -o ffrl+ -j RETURN # iptables -t nat -A ffrl-nat -s 100.64.3.172/31 -o ffrl+ -j RETURN # iptables -t nat -A ffrl-nat -s 10.181.0.0/16 -o ffrl+ -j SNAT --to-source 185.66.194.27 # iptables -t nat -A POSTROUTING -s 10.181.0.0/16 -o ffrl+ -j ffrl-nat # iptables -A FORWARD -i ggrzBR -o ffrl+ -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu # iptables -A FORWARD -i ffrl+ -o ggrzBR -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu # iptables -t raw -A PREROUTING -d 5.196.74.176/32 -i ggrzBR -p udp -m multiport --dports 10181,20181 -m comment --comment "drop VPN from mesh" -j DROP # iptables -t raw -A PREROUTING -d 193.28.153.11/32 -i ggrzBR -p udp -m multiport --dports 10181,20181 -m comment --comment "drop VPN from mesh" -j DROP # iptables -t raw -A PREROUTING -d 136.243.179.182/32 -i ggrzBR -p udp -m multiport --dports 10181,20181 -m comment --comment "drop VPN from mesh" -j DROP
IPv6:
# ip6tables -t filter -A INPUT -i eth0 -p tcp --dport 179 -j REJECT # ip6tables -t filter -A INPUT -i exitVPN -p tcp --dport 179 -j REJECT # ip6tables -t filter -A INPUT -i ggrzBR -p tcp --dport 179 -j REJECT # ip6tables -t nat -A POSTROUTING -o exitVPN -j MASQUERADE # ip6tables -A FORWARD -i ggrzBR -o ffrl+ -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu # ip6tables -A FORWARD -i ffrl+ -o ggrzBR -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu # ip6tables -t raw -A PREROUTING -d 2a01:4f8:172:19ea:201::182/128 -i ggrzBR -p udp -m multiport --dports 10181,20181 -m comment --comment "drop VPN from mesh" -j DROP # ip6tables -t raw -A PREROUTING -d 2a02:ff80:1003:2::2/128 -i ggrzBR -p udp -m multiport --dports 10181,20181 -m comment --comment "drop VPN from mesh" -j DROP # ip6tables -t raw -A PREROUTING -d 2001:41d0:e:8b0::1/128 -i ggrzBR -p udp -m multiport --dports 10181,20181 -m comment --comment "drop VPN from mesh" -j DROP
Die Zeilen mit --dport 587 bewirken, daß der SMTP-Submission-Port nicht über das VPN geroutet wird. Das ist erforderlich, da die meisten VPN-Anbieter zur Spam-Verhinderung die Ports 25, 465 und 587 sperren.
Im Verzeichnis /etc/conf.d wird in den Dateien iptables und ip6tables die Zeile SAVE_ON_STOP="yes" geändert in SAVE_ON_STOP="no". Anschließend werden die angelegten Regeln gespeichert und iptables in den Runlevel default aufgenommen:
# rc-service iptables save # rc-service iptables start # rc-update add iptables default # rc-service ip6tables save # rc-service ip6tables start # rc-update add ip6tables default
Layer 2
B.A.T.M.A.N. verfügt über die sinnvolle Funktionatität, im Server-Mode DHCP-Broadcasts von Clients nicht weiterzuleiten. Diese werden damit nur vom lokalen DHCP-Server beantwortet, welcher den Clients sich selbst als Default Gateway und DNS-Server nennt. Für IPv6 fehlt in B.A.T.M.A.N. eine analoge Funktionalität für die Router Advertisements. Damit sehen die Clients alle Gateways einer Mesh-Wolke als mögliches Default Gateway und nicht das nächste (wo der FastD-Tunnel des Knotens endet. Um das zu verhindern, wird "ebtables" genutzt:
# emerge -av ebtables
Analog zu iptables wird in /etc/conf.d/ebtables die Zeile SAVE_ON_STOP="yes" geändert in SAVE_ON_STOP="no". Anschließend wird die Konfiguration erzeugt, gespeicher und in den Default Runlevel aufgenommen:
# ebtables -A FORWARD -p IPv6 -i ggrzBAT --ip6-proto ipv6-icmp --ip6-icmp-type router-advertisement -j DROP # rc-service ebtables save # rc-service ebtables start # rc-update add ebtables default
Dienste
NTP
Bei Verschlüsselung, fürs Logging u.a. ist eine genaue Zeit wichtig. Dafür wird NTP installiert:
# emerge -av ntp
Die Konfiguration wird dann wie folgt angepaßt:
/etc/ntp.conf:
# /etc/ntp.conf, configuration for ntpd; see ntp.conf(5) for help driftfile /var/lib/ntp/ntp.drift # listen at localhost and mesh only interface ignore wildcard interface listen 127.0.0.1 interface listen ::1 interface listen 10.181.0.11 interface listen fdb5:78b:64cc::11 # only use local time, synced with kvm host time tos orphan 1 # By default, exchange time with everybody, but don't allow configuration. restrict -4 default kod notrap nomodify nopeer noquery restrict -6 default kod notrap nomodify nopeer noquery # Local users may interrogate the ntp server more closely. restrict 127.0.0.1 restrict ::1
Ohne die Angabe von "server", stattdessen mit "tos orphan 1" werden keine externen Zeitserver abgefragt, sondern nur die Systemzeit an andere NTP-Clients verteilt. Das ist sinnvoll, da dieses Gateway in einer virtuellen Maschine auf einem KVM-Host läuft. Dieser Host gibt seine per NTP aktuell gehaltene Zeit an die VMs weiter.
Damit der NTP-Daemon erst startet, wenn das Mesh-Interface vorhanden ist (daran soll er sich ja binden), wird folg. ergänzt:
/etc/conf.d/ntpd:
# soll sich an die Mesh-Interfaces binden, # die sollten also da sein rc_need="net.ggrzBAT"
Abschließend wird der Daemon gestartet:
# /etc/init.d/ntpd start # rc-update add ntpd default
Dnsmasq
Als Server für DNS und DHCP verwenden wir Dnsmasq:
# echo "net-dns/dnsmasq auth-dns dhcp-tools" >> /etc/portage/package.use/Freifunk # emerge -av dnsmasq
Die Konfiguration sollte dann so aussehen
/etc/dnsmasq.conf:
### Allgemeines conf-dir=/etc/dnsmasq.d bogus-priv no-resolv no-poll expand-hosts domain-needed cache-size=4096 strict-order interface=ggrzBAT bind-interfaces ### DNS # Hetzner DNS Server (später evtl. andere nehmen) server=213.133.100.100 server=213.133.99.99 server=213.133.98.98 local=/ffggrz/ domain=ffggrz ### DHCP / RA dhcp-authoritative #log-dhcp dhcp-range=10.181.1.1,10.181.2.254,3m dhcp-option=option:router,10.181.0.11 dhcp-option=option:dns-server,10.181.0.11,8.8.8.8 dhcp-option=option:ntp-server,10.181.0.11 dhcp-option=option:domain-search,ffggrz ### MTU 1280 ##dhcp-option-force=26,1280 dhcp-range=set:ggrzv6,::,constructor:ggrzBAT,slaac,ra-only,3m dhcp-option=tag:ffsv6,option6:dns-server,[fdb5:78b:64cc::11] dhcp-option=tag:ffsv6,option6:ntp-server,[fdb5:78b:64cc::11] dhcp-option=tag:ffsv6,option6:domain-search,ffggrz enable-ra ##ra-param=ggrzBAT,low,0,0 ra-param=ggrzBAT,high,60,1200
Falls das Verzeichnis /etc/dnsmasq.d noch nicht existiert, wird dieses jetzt angelegt:
# mkdir /etc/dnsmasq.d
Auch Dnsmasq soll erst starten, wenn das Mesh-Interface vorhanden ist:
/etc/conf.d/dnsmasq:
# soll sich an die Mesh-Interfaces binden, # die sollten also da sein rc_need="net.ggrzBAT"
Nun wird Dnsmasq noch gestartet und in den Default Runlevel aufgenommen:
# /etc/init.d/dnsmasq start # rc-update add dnsmasq default
Karte, Listen
Backend
Zur Darstellung aktiver Nodes und Gateway in einer Karte bzw. Liste erfolgt die Sammlung und Aufbereitung der nötigen Daten mittels A.L.F.R.E.D.:
# emerge -av alfred
A.L.F.R.E.D. wird das zu nutzende Interface mitgeteilt, außerdem soll der Start erst nach dem Mesh-Interface erfolgen:
/etc/conf.d/alfred:
# B.A.T.M.A.N. interface ALFRED_IFCBAT="ggrzBAT" # soll sich an die Mesh-Interfaces binden, # die sollten also da sein rc_need="net.ggrzBAT"
Nun wird A.L.F.R.E.D. noch gestartet und in den Default Runlevel aufgenommen:
# /etc/init.d/alfred start # rc-update add alfred default
Das Auslesen der Daten und die Übergabe an den Mapviewer erfolgt über das ffmap-Backend:
# emerge -av ffmap-backend
Dieses wird dann mittels Cron-Job minütlich abgearbeitet (s. /etc/cron.d/ffmap-backend). Die erzeugten Daten landen in /var/www/localhost/htdocs/data und werden dort vom Webserver (Nginx) für das Frontend zur Verfügung gestellt.
Frontend
Als Frontend verwenden wir den Meshviewer. Dieser wird nicht auf dem Gateway, sondern auf den Server für das Webportal installiert. Die folgenden Schritte werden also dort durchgeführt.
# cd /root # git clone https://github.com/tcatm/meshviewer.git # cd meshviewer # npm install # npm install bower grunt-cli # node_modules/.bin/bower --allow-root install # node_modules/.bin/grunt
Anschließend erfolgt die Konfiguration. Dazu wird die Beispieldatei config.json.example nach build/config.json kopiert und angepaßt.
- Details
- Geschrieben von: Jörg
- Kategorie: Gateways
Mit dieser Anleitung ist unser Jabber-Server aufgesetzt worden. Es handelt sich um eine Debian-VM. Darin wurde als XMPP-Server Prosody verwendet.
Die folgenden Schritte installieren den Server mit Debian-Bordmitteln:
- apt-get update
- apt-get install prosody
Anschließend muss die Konfiguration angepasst werden, damit der Server die Anfragen von Clients ordnungsgemäß behandeln kann. Es sind jeweils nur die Ergänzungen bzw. Änderung der Standardkonfiguration gezeigt.
Es wurde mehrere Domains hinterlegt für die der Server zuständig ist (chat.ffggrz (FF-intern), chat.ffggrz.de (Internet)). Zusätzlich wurde der Multiuserchat (MUC/Conferencing) aktiviert und der Pfad zu dem noch anzulegenden Zertifikat hinterlegt.
Alle Domains verwenden das gleiche Zertifikat. Die Seiten sind als SubjectAltName hinterlegt, so dass es nicht zu Zertifikatsfehlern kommen sollte.
- nano /etc/prosody/prosody.cfg.lua
allow_registration = true admins = { "Diese E-Mail-Adresse ist vor Spambots geschützt! Zur Anzeige muss JavaScript eingeschaltet sein. " } ssl = { key = "/var/lib/prosody/chat.ffggrz.de.key"; certificate = "/var/lib/prosody/chat.ffggrz.de.crt"; } VirtualHost "chat.ffggrz" enabled = true VirtualHost "chat.ffggrz.de" enabled = true Component "conference.chat.ffggrz" "muc" Component "conference.chat.ffggrz.de" "muc"
Es wird ein neuer Administrator-Account angelegt.
- prosodyctl adduser
Diese E-Mail-Adresse ist vor Spambots geschützt! Zur Anzeige muss JavaScript eingeschaltet sein.
Um ein selbstsigniertes Zertifikat für den Server zu generieren, gibt es seit Prosody 0.9+ eine einfache Möglichkeit das erledigen zu lassen.
Mit folgendem Befehl wurde das Zertifikat für unsere Domains generiert:
- prosodyctl cert generate chat.ffggrz.de chat.ffggrz
Der Inhalt des Zertifikats kann mit folgendem Befehl auch auf der Kommandozeile einfach überprüft werden.
- openssl x509 -text -noout -in /var/lib/prosody/chat.ffggrz.de.crt
- Details
- Geschrieben von: Eric
- Kategorie: Dienste
Falls jemand mit einfachen Mitteln ins Mesh will (aber mit üblichen Mitteln dies nicht kann) darf mir eine EMail schreiben um einen Zugang zum OpenVPN zu erhalten.
Raspberry PI / Linux
Grundkonfiguration
OpenVPN installieren:
sudo apt-get install openvpn
Die Dateien aus der Zip in /etc/openvpn/ kippen und anpassen:
sudo mv ~/ffggrz_mesh_marcus.zip /etc/openvpn cd /etc/openvpn/ sudo unzip ffggrz_mesh_marcus.zip sudo mv ffggrz_mesh.ovpn ffggrz_mesh.conf
feste IP
Den Pi abgewöhnen den dhcp-Client zu nutzen:
/etc/dhcpcd.conf
denyinterfaces ggrzOVPN
Feste IP für das Interface konfigurieren:
/etc/network/interfaces
auto ggrzOVPN iface ggrzOVPN inet static address 10.181.0.123 netmask 255.255.192.0 dns-nameservers 10.181.0.12 dns-search ffggrz iface ggrzOVPN inet6 static address fdb5:78b:64cc::123 netmask 64
Starten
sudo systemctl start openvpn@ffggrz_mesh.service
Damit OpenVPN sich bei Systemstart automatisch verbindet bitte folgende Zeile aktivieren:
/etc/default/openvpn
AUTOSTART="all"
Windows
Todo: Anleitung für Windows vervollständigen
https://openvpn.net/index.php/open-source/downloads.html
Zip in c:
Program Files
OpenVPN
config
kippen
OpenVPN-GUI als Administrator starten!
- Details
- Geschrieben von: Eric
- Kategorie: Dienste
Jeder der eine E-Mail-Adresse oder Umleitung benötigt (z.B. für einen Node) kann sich bitte per Kontakt melden. :)
SPAM landet automatisch im "spam"-Ordner, dieser wird aber erst mit der ersten SPAM-EMail erstellt.
- SMTP: mail.freifunk-gera-greiz.de (IPv4)
- SMTP-Auth notwendig (kein SMTP-After-POP möglich!)
- Unverschlüsselt: Port 25
- STARTTLS: Port 587
- SSL/TLS: Port 465
- IMAP: mail.freifunk-gera-greiz.de (IPv4)
- Unverschlüsselt: Port 143
- STARTTLS: Port 143
- SSL/TLS: Port 993
- POP3: mail.freifunk-gera-greiz.de (IPv4)
- Unverschlüsselt: Port 110
- STARTTLS: Port 110
- SSL/TLS: 995
- Verfügbare Domains: @freifunk-gera-greiz.de und @ffggrz.de
- Webmail: https://mail.freifunk-gera-greiz.de/
- Passwort ändern: https://mail.freifunk-gera-greiz.de/password/
- Administration: https://mail.freifunk-gera-greiz.de/admin/ (nur verfügbar für Admins)
- Getestet mit:
- Thunderbird
- K9 Mail (Android)
- Mail (OS X)
- EMail (Android)
- Details
- Geschrieben von: Eric
- Kategorie: Dienste
Test vom 4. Oktober 2018
Standort |
Zeit |
Ping4 |
Ping6 gw1 intern |
Ping4 Internet |
Ping6 Internet |
Gateway |
Speed |
Speed Internet (u/d Mbps) |
Downlinks | Bemerkung |
---|---|---|---|---|---|---|---|---|---|---|
FWS (Feuerwache Süd) | 10:00 | ✔ | ✔ | ✔ | ✔ | Server-002 | keine Messung | 6,9/10,2 | 2 | Internet gut nutzbar |
KHS (Karl-Harnisch-Stadion) | 10:30 | ✔ | ✔ | ✔ | ✔ | gw3 | 2,4/1,0 | 0,6/- | 0 | nicht nutzbar |
GSZ (Schule Zwötzen) | 10:50 | ✔ | ✔ | ✔ | ✔ | gw1 | 1,6/5,9 | 1,4/7,6 | 1 | Internet gut nutzbar |
KUK (Kultur- & Kongreßzentr.) | 14:15 | ✔ | ✔ | ✔ | ✔ | Server-002 | 2,6/6,5 | 1,3/3,6 | 0 | Internet nutzbar |
FWM (Feuerwache Mitte) | 12:10 | ✔ | ✔ | ✔ | ✔ | gw1 | 4,0/7,2 | 2,4/5,6 | 1 | Internet gut nutzbar |
Marienkirche | 13:40 | ✔ | ✔ | ✔ | ✔ | gw2 | 2,2/4,2 | 1,8/1,0 | 0 | Internet langsam |
SRH Klinik (an gw2) | 11:30 | ✘ | ✔ | ✘ | ✔ | gw2 | 1,3/9,6 | 0,7/0,7 | nicht nutzbar | |
SRH Klinik (an gw1) | 11:40 | ✔ | ✔ | ✔ | ✔ | gw1 | 35,2/22,2 | 17,0/20,2 | Internet gut nutzbar | |
Unitas Network | 08:30 | ✔ | ✔ | ✔ | ✔ | gw3 | 6,5/11,4 | 3,9/5,7 | Internet gut nutzbar |
Es wurde eine Verbindung zu einem der am Standort vorhandenen Freifunk-Knoten auf GLUON-Basis verbunden. Benutzt wurde ein Notebook mit Linux und ein NETSCOUT AirCheck G2.
Das AirCheck G2 diente mittels AutoCheck der schnellen Überprüfung der Umgebung und Verbindung ins Freifunk-Netz. Genauere Daten dieser Tests werden noch ausgewertet und hier evtl. noch nachgeliefert. Außerdem wurden die Geschwindigkeitsmessungen damit durchgeführt. Gegenstellen waren das jeweilige Gateway (interne IP-Adresse) und zur Geschwindigkeitsmessung ins Internet der Rootserver der Unitas Network GmbH. Dafür wird iPerf3 genutzt, auf den Gateways als Server, auf dem AirCheck G2 als Client im TCP-Mode.
Da das AirCheck G2 leider kein IPv6 beherrscht, wurden diese Tests mittels Notebook durchgeführt. Es wurde ein Ping auf gw1.ffggrz und server1.unitas-network.de durchgeführt. Damit konnte die interne und externe Namensauflösung und Erreichbarkeit überprüft werden. Außerdem wurde subjektiv die Nutzbarkeit des Internets durch den Aufruf verschiedener Seiten geprüft.
Die Anzahl der Downlinks bezeichnet die Zahl der Knoten, welche den Standort als Uplink nutzen und über keinen anderen Anschluß (VPN, Mesh) verfügen.
- Details
- Geschrieben von: Jörg
- Kategorie: Backbone