Introduction & Quick-start
Most of us are into free wireless mesh networks. We’re fascinated by the idea of deploying a bunch of OpenWRT routers, that magically connect to each other to span large mesh cloud.
Unfortunately, doing so is very hard - the various different options for mesh routing protocols and network designs can be overwhelming.
Many community networks deploy complex configurations. They release custom firmware blobs using self-written scripts to customize OpenWRT images. Usually, these firmware blobs are tight to a specific network by including network addresses or wifi identifiers.
Some Freifunk firmware files even include vpn-server-addresses, rendering them useless for other communities or people living just a few kilometers away.
Here, configuration becomes opaque and thus hard to understand: It’s buried in binary images using custom software and different, sometimes hackish startup-scripts.
Build systems such as Gluon provide a heavy-weight abstraction to OpenWRT. By creating a Domain-Specific-Language (DSL), all relevant OpenWRT settings are duplicated into a site-model, which is then used to describe a specific community network. Although not having explicit restrictions, this site-model focuses on backend-server driven networks, somewhat missing the point of a wifi mesh network. Very little changes to the configuration require a build using the full OpenWRT buildroot.
Node-config is trying to jump in here by providing a comprehensible configuration. Without having a shiny user interface in its core, node-config is focusing on network enthusiasts. It explains all necessary OpenWRT settings for a simple wifi mesh, while providing a complete and easy-to-use setup.
This documentation is devided into tree chapters: Introduction & Quick-start provides an overview including a hands-on. It helps to get node-config running in a few minutes. The chapter Configuration in node-config takes a deep dive into the configuration: It outlines all things done to an OpenWRT router by node-config. The last chapter Advanced Topics highlights the background. It illustrates node-config’s design considerations and explains the concepts in use. Building packages and firmware is also addressed in the last chapter.
Let’s get started.
1. What node-config is
Node-config is just a bunch of uci configuration files including a scripts to apply them. It is copied to plain OpenWRT routers running OpenWRT 18.06 and merged into the existing configuration. It configures routing, network- and wireless interfaces as well as network services such as dhcp and radv.
It spans a mesh network using both babel and batman-adv to provide roaming and hierarchical routing capabilities. The network is IPv4 and IPv6 dual-stack.
You can use and understand node-config as:
|
A git-repository is available at https://github.com/yanosz/node-config - for help and discussions please subscribe to the wlanware mailing list.
2. Quick-start
You need OpenWRT 18.06 installed on a router and enough free flash space (~2 MB). The router has to be connected to the internet (wan port) an to your computer (pc or laptop using the lan port)
It helps to be familiar with a unix terminal (i.e. Mac OS, Linux) since you need to use ssh to connect to your router. In addition, git is required:
git clone https://github.com/yanosz/node-config.git
cd node-config; scp -r freifunk root@192.168.1.1:/lib
ssh root@192.168.1.1 /lib/freifunk/install.sh
It is assumed, that your router is reachable at 192.168.1.1
(OpenWRT default). Using git
, scp
and ssh
node-config is cloned and then copied to your router. It is applied using [_install_sh].
|
3. Using packages
Packages can be used instead of copying the filesystem tree using git and scp.
For testing, opkg packages are available at: https://kbu.freifunk.net/files/node-config/. Packages are built using an additional project integrated into GitLab CI.
wget -O /etc/opkg/keys/cca6643a8ac2f277 http://opkg.kbu.freifunk.net/node-config/cca6643a8ac2f277
echo "src/gz nc http://opkg.kbu.freifunk.net/node-config/packages" >> /etc/opkg/customfeeds.conf
opkg update
opkg install node-config node-config-openvpn node-config-pptp
Reboot the router, after installing the packages.
For setting IPv4 and IPv6 networks open a new ssh session execute /lib/freifunk/set_ip.sh
.
When executing opkg install node-config
, core components are installed, only - openvpn and pptp are not available.
|
4. Internet Sharing
4.1. Direct Exit
To share the routers WAN uplink in the mesh cloud, you have to enable it.
uci set network.internet_share.disabled=0
uci set network.internet_share6.disabled=0
uci firewall.freifunk_internet.dest='wan'
uci commit firewall
uci commet network
/etc/init.d/firewall restart
/etc/init.d/network restart
By enabling internet_share and internet_share6 , WAN routes will be copied to the
mesh routing table. uci firewall.freifunk_internet.dest='wan' enables forwarding.
|
4.2. Using a VPN provider
To use a vpn tunnel (i.e. mullvad),
you can use a configuration in /lib/freifunk/vpn
and activate it by editing /etc/config/openvpn
.
See /etc/config/openvpn for details.
If you want to use a provider not included in
/lib/freifunk/vpn , you can place your provider’s configuration there.
Mind adding route-nopull , script-security 2 and up /lib/freifunk/vpn/up.sh for default route handling.
Have a look at existing VPN configurations for example. Also mind setting dev vpn-nat to use
the correct network interface.
|
5. Git directory structure
All configuration can be found in /freifunk/initial_configuration
. Other directories contain scripts,
build files and documentation.
Path |
Contents |
|
Directory root, including readme’s, the project’s Makefile and CI-configuration |
|
Documentation including the asciidoc source of this manual |
|
Configuration including scripts |
|
OpenWRT configuration (uci) |
|
Shared routines for scripts |
|
OpenVPN exit configuration for different providers |
|
Makefiles and other files for creating OpenWRT packages |
Configuration in node-config
Hold your breath - we’ll take a deep dive into node-config’s Configuration. Don’t get lost in details - try to see the big picture.
The configuration is documented on a per-file basis - each OpenWRT configuration is explained individually. Figure 1 shows the system from a birds eye perspective.
Node-config creates a hand full of interfaces: wlan0, wlan1, bat0, br-freifunk as well as vpn interfaces like tap0 and ppp0. They are configured as follows:
-
wlan0 and wlan1 are set up by node-config
-
wlan0 is running in master mode. It’s used by all clients.
-
wlan1 is running in ad-hoc (or 802.11s) mode. This interface is used for meshing.
-
-
ethX (WAN) and ethY (LAN) are created by OpenWRT. They are not configured by node-config.
-
The LAN interface is used for a management (SSH / LuCI).
-
The WAN interface connects to the internet. It can be used for internet sharing.
-
Optionally, a VPN (openvpn, pptp, wiregard) can tunnel internet traffic.
-
-
bat0 is the batman-adv interface of the system. It utilizes the ad-hoc interface for meshing.
-
br-freifunk is central: It bridges all clients (wlan0) into the roaming domain (wlan1).
-
Other vpn interfaces (fastd: tap0, l2tp: l2tpeth0) are optional: They created and assigned to batman-adv and / or babel to mesh and roam using wires or directed wireless links.
Some interfaces are used by services to provide connectivity:
-
DHCP and radv services are running on br-freifunk. They hand out ip-addresses to clients. However, these dropped on bat0 using ebtables to reduce broadcast / multicast traffic.
-
babel is running on the wlan1 interface and all vpn interfaces used for mesh routing.
Mind not to bind the optional vpn interfaces to br-freifunk / bat0. It is easy to have a catch-22. |
Some interfaces are missing in the picture - have a look at the actual system:
-
Most interfaces have an IPv6 counterpart. These duplicates are needed by OpenWRT
-
internet_share
is a duplicate of the WAN interfaces. It’s used for copying WAN routes into the freifunk routing tables. -
By default, node-config creates two optional interfaces using fastd. One is for Routing within Freifunk communities (enabled), while the other is part of the Freifunk / Gluon supernode template (disabled)
6. /etc/config/wireless
The wireless configuration is generated using a shell script Additional information in wireless configuration can be found in the OpenWRT wiki. the OpenWRT wiki.
Please adjust if needed
wireless.sh
#!/bin/sh
if [ -z $(uci get wireless.radio0) ]; then
echo "No wifi device found"
fi
radio0_disabled=$(uci get wireless.radio0.disabled)
radio0_default=$(uci get wireless.default_radio0)
if [ "$radio0_disabled" == "1" ] && [ "$radio0_default" == "wifi-iface" ];then
echo "Disabled adapter with default configuration found - disabling default configuration"
uci set wireless.default_radio0.disabled='1'
fi
echo "Creating wifi interface on radio0 - Assuming 2.4 Ghz - Using channel 1"
uci -q batch <<EOF
set wireless.radio0.disabled='0'
set wireless.radio0.channel='1' # Radio settings
set wireless.radio0.htmode='HT20'
set wireless.radio0.country='DE'
set wireless.wifi_freifunk='wifi-iface' # 1. wifi: Accesspoint
set wireless.wifi_freifunk.device='radio0'
set wireless.wifi_freifunk.network='freifunk'
set wireless.wifi_freifunk.mode='ap'
set wireless.wifi_freifunk.ssid='Freifunk'
set wireless.wifi_mesh='wifi-iface' # 2. wifi: ad-Hoc mesh
set wireless.wifi_mesh.device='radio0'
set wireless.wifi_mesh.network='mesh babel_mesh'
set wireless.wifi_mesh.mode='adhoc'
set wireless.wifi_mesh.ssid='42:42:42:42:42:42'
set wireless.wifi_mesh.bssid='42:42:42:42:42:42'
set wireless.wifi_mesh.mcast_rate='12000'
EOF
radio1=$(uci get wireless.radio1)
if [ $radio1 ];then
echo "Found 2nd wifi-interface - Assuming 5Ghz - Using channel 36"
radio1_disabled=$(uci get wireless.radio1.disabled)
radio1_default=$(uci get wireless.default_radio1)
if [ "$radio1_disabled" == "1" ] && [ "$radio1_default" == "wifi-iface" ];then
echo "Disabled adapter with default configuration found - disabling default configuration"
uci set wireless.default_radio1.disabled='1'
fi
uci -q batch <<EOB
set wireless.radio1.disabled='0'
set wireless.radio1.channel='36' # radio settings
set wireless.radio1.country='DE'
set wireless.radio1.htmode='HT40'
set wireless.wifi_freifunk5='wifi-iface' # 1. wifi: accesspoint
set wireless.wifi_freifunk5.device='radio1'
set wireless.wifi_freifunk5.network='freifunk'
set wireless.wifi_freifunk5.mode='ap'
set wireless.wifi_freifunk5.ssid='Freifunk'
set wireless.wifi_mesh5='wifi-iface' # 2. wifi: ad-Hoc mesh
set wireless.wifi_mesh5.device='radio1'
set wireless.wifi_mesh5.network='mesh5 babel_mesh5'
set wireless.wifi_mesh5.mode='adhoc'
set wireless.wifi_mesh5.ssid='42:42:42:42:42:42'
set wireless.wifi_mesh5.bssid='42:42:42:42:42:42'
set wireless.wifi_mesh5.mcast_rate='12000'
EOB
fi
uci commit wireless
wireless.sh
:-
It detects how many radios are available
-
If there’s a radio, 2.4 Ghz is assumed. It’s locked to channel 1 and enabled
-
If there’s a second radio, 5 Ghz is assumed. It’s locked to channel 36 and enabled.
-
Other radios are ignored
-
-
If unused OpenWRT default configurations are present on a radio, they are disabled.
-
An ad-hoc interface with SSID
42:42:42:42:42:42
and an access point interface with SSIDFreifunk
is created on all radios detected before. All ad-hoc interfaces use a broadcast rate of 12 MBit/s. While the 5 Ghz radio is using 40 Mhz, the 2.4 GHz has 20 MHz.
6.1. Naming the Service Set ID (SSID):
You can adjust the BSSID and SSID according to your needs. Creating separated networks requires using different SSIDs. For roaming, all SSID of a network must be the same:
On the one hand, moving to an accesspoint with a different SSID will reinitialize the wifi card - all active connections will be lost. On the other hand, all mesh stations need the same SSID to connect to each other. The network will fall apart, if they differ.
Keep in mind, that the Extended Service Set ID (ESSID) is called SSID in OpenWRT. It is the network name shown on clients. The Basic Service Set ID (BSSID) defines the technical identifier of the ad-hoc segment. By its design, ad-hoc networks can fall apart by mistakenly generating different BSSIDs for the same logical segment. Thus the BSSID needs set to fixed value. The issue is addressed by IEEE 802.11s.
For more details on service sets have a look at wikipedia.
6.2. Using IEEE 802.11s
You can use the new IEEE 802.11s mesh mode instead of the new ad-hoc. To do so, you need to modify
wireless.sh
.
wireless.sh
- example for radio0 (first radio, 2.4 Ghz usually).# ...
set wireless.wifi_mesh='wifi-iface'
set wireless.wifi_mesh.device='radio0'
set wireless.wifi_mesh.network='mesh babel_mesh'
set wireless.wifi_mesh.mode='mesh'
set wireless.wifi_mesh.mesh_id='42:42:42:42:42:42'
set wireless.wifi_mesh_fwding='0'
set wireless.wifi_mesh.mcast_rate='12000'
# ...
When modifying the 5 Ghz network, use wifi_mesh5
instead of wifi_mesh
.
Setting mesh_fwding='0'
disables forwarding in the IEEE 802.11s mesh network.
Forwarding is disabled, because Babel and batman-adv need to see the topology on their own.
Forwarding would hide the structure of network from both babel and batman-adv.
In addition, it is redundant to batman-adv.
If experimenting with IEEE 802.11s mesh forwarding:
|
7. /etc/config/batman-adv
Batman-adv is used for roaming. It uses all wifi ad-hoc interface (2.4 Ghz and 5 Ghz). In addition, VPN (l2tp, fastd) interfaces can be added to improving roaming when no radio contact is available.
The configuration does not contain any network interfaces. The mapping is done in
/etc/config/network
. More details configuration options are listed in the
Open-Mesh wiki.
batman-adv.uci
creates a mesh (bat0
) using these options.package batman-adv
# Batman-adv is used for roaming
# Every node is a batman-adv gateway, since it runs a dhcp service
# DAT, aggregated_ogms and bridge_loop_avoidance are enabled.
config mesh 'bat0'
option orig_interval '5000'
option bridge_loop_avoidance '1'
option gw_mode 'server'
option fragmentation '1'
option aggregated_ogms '1'
option distributed_arp_table '1'
Having hardly any mobility in a Freifunk-style network, an originator interval of 5 seconds is enough. Bridge loop avoidance, the distributed arp table and ogm aggregation is enabled.
Fragmentation is enabled for roaming using wired interfaces. Usually, ethernet, l2tp or fastd connections cannot transmit a complete batman-adv frame using up to 1532 bytes without fragmentation.
8. /etc/config/network
The network configuration is probably the most complex part of node-config. Be brave, you’ll make it :-).
Have a look at the https://openwrt.org/docs/guide-user/base-system/basic-networking for additional help on OpenWRT’s network configuration.
8.1. Network Interfaces
Let’s look at the network interfaces first (cf. network.ci
).
/etc/config/network
# Freifunk-Interface - main interface of the node
# This bridge has the configured IPv4 and IPv6 networks
# It's using the Freifunk routing table having a dual-stack configuration
# Using ip6assign und ip6class the ula space and DHCPv6 PD prefixes are used for delegation
config interface 'freifunk'
option disabled '1'
option ifname 'bat0'
option type 'bridge'
option auto '1'
option proto 'static'
option ipaddr '10.159.64.1'
option netmask '255.255.255.0'
option ip6prefix 'fdd3:5d16:b5dd:f064::/64'
option ip6assign '64'
list ip6class 'vpn6'
list ip6class 'freifunk'
list ip6class 'internet_share6'
# bat0 interface - used in the br-freifunk bridge to access batman-adv
config interface 'bat0'
option proto 'none'
option ifname 'bat0'
# The fastd interface is used for Freifunk Routing. Being included in babel but not in fastd,
# Other Mesh-segments are reachable using a vpn.
# For IPv4 the node's IP address is used with a /32 netmask
# For IPv6 only host routes are used
# It's disabled by default an enabled, when IP-addresses are set (i.e. using set_ip.sh)
config interface 'fastd'
option disabled '1'
option ifname 'tap-icvpn'
option proto 'static'
option ipaddr '10.159.64.1'
option netmask '255.255.255.255'
option ip4table '66'
option ip6table '66'
# The VPN is used for sharing internet using a VPN tunnel. Both IPv4 and IPv6 configurations are provided
config interface 'vpn'
option proto 'none'
option ifname 'vpn-nat'
option ip4table '66'
option ip6table '66'
config interface 'vpn6'
option proto 'dhcpv6'
option ifname 'vpn-nat'
option ip6table '66'
# Batman-adv meshes have ot be configured for 2.4 and 5 Ghz sperately.
# An ad-hoc wifi interface is mapped to each interface definition
# 2.4 GHz
config interface 'mesh'
option proto 'batadv'
option mtu '1532'
option mesh 'bat0'
# 5 Ghz
config interface 'mesh5'
option proto 'batadv'
option mtu '1532'
option mesh 'bat0'
# When used as a Freifunk/Gluon supernode, an additional fastd interfaces has to be added to babel.
# It is disabled by default
config interface 'mesh_supernode'
option disabled '1'
option proto 'batadv'
option mtu '1532'
option mesh 'bat0'
option ifname 'tap-supernode'
# The share the internet direct, the wan interfaces has to be re-definied using a different routing table
# This copies all WAN routes to table 66
# This has to be done for IPv4 and IPv6 separately
config interface 'internet_share'
option ifname '@wan'
option proto 'dhcp'
option ip4table '66'
option disabled '1'
config interface 'internet_share6'
option ifname '@wan'
option ip6table '66'
option disabled '1'
option proto 'dhcpv6'
That is it :-). Try matching these interfaces with bird’s eye perspective picture in the beginning (Figure 1).
You might need to adjust some interfaces according to your local
setup (i.e. internet_share - use proto 'static' instead of proto 'dhcp' ). All vpn and fastd interfaces can be removed, if vpn connections are not in use.
|
8.2. Routes & Rules
Node-config uses a dedicated routing table (66). This allows separating the mesh from uplink and management networks. To build this table, all relevant IPv4 and IPv6 routes are duplicated. In addition, IP rules assign mesh traffic to this table.
Have a look at the Linux Advanced Routing & Traffic Control HOWTO for more information on policy based routing.
network.uci
# The configured IPv4 network is reachable in the freifunk bridge
config route 'route4_node_subnet'
option interface 'freifunk'
option target '10.159.64.0'
option netmask '255.255.255.0'
option gateway '0.0.0.0'
option table '66'
# The configured IPv6 network is reachable in the freifunk bridge
config route6 'route_6_node_subnet'
option interface 'freifunk'
option target 'fdd3:5d16:b5dd:f064::/64'
option table '66'
# For both babel interfaces (2.4 GHz, 5 GHz) there's a host route for the interface address
config interface 'babel_mesh'
option disabled '1'
option proto 'static'
option ipaddr '10.159.64.1'
option netmask '255.255.255.255'
option ip4table '66'
option ip6table '66'
config interface 'babel_mesh5'
option disabled '1'
option proto 'static'
option ipaddr '10.159.64.1'
option netmask '255.255.255.255'
option ip4table '66'
option ip6table '66'
# Use table 66 for all Freifunk traffic
config rule 'rule4_freifunk_out'
option out 'freifunk'
option lookup '66'
option priority '66'
config rule6 'rule6_freifunk_out'
option out 'freifunk'
option lookup '66'
option priority '66'
config rule 'rule4_freifunk_in'
option in 'freifunk'
option lookup '66'
option priority '66'
config rule6 'rule6_freifunk_in'
option in 'freifunk'
option lookup '66'
option priority '66'
Unfortunately, OpenWRT cannot create all rules using /etc/config/network
. Thus
they’re created using the firewall script /etc/firewall.user
. Being part of node-config
rules.sh
modies the the firewall script. || true
prevents firewall.user
from failing, if
an interface is not available, yet.
|
firewall.user
mv /etc/rc.local /tmp/rc.local
echo "
#!/bin/sh
# Hack: https://lists.openwrt.org/pipermail/openwrt-users/2016-March/004150.html
# Since /etc/config/network cannot be used for intering rules, the firewall script is used
# Pref 66 is important. It prevents rules with priority 0 (for local)
ip rule del iif wlan0 lookup 66 pref 66 || true
ip rule del oif wlan0 lookup 66 pref 66 || true
ip rule del iif wlan1 lookup 66 pref 66 || true
ip rule del oif wlan1 lookup 66 pref 66 || true
ip rule del iif tap-icvpn lookup 66 pref 66 || true
ip rule del oif tap-icvpn lookup 66 pref 66 || true
ip rule add iif wlan0 lookup 66 pref 66
ip rule add oif wlan0 lookup 66 pref 66
ip rule add iif wlan1 lookup 66 pref 66
ip rule add oif wlan1 lookup 66 pref 66
ip rule add iif tap-icvpn lookup 66 pref 66
ip rule add oif tap-icvpn lookup 66 pref 66
ip -6 rule del iif wlan0 lookup 66 pref 66 || true
ip -6 rule del oif wlan0 lookup 66 pref 66 || true
ip -6 rule del iif wlan1 lookup 66 pref 66 || true
ip -6 rule del oif wlan1 lookup 66 pref 66 || true
ip -6 rule del iif tap-icvpn lookup 66 pref 66 || true
ip -6 rule del oif tap-icvpn lookup 66 pref 66 || true
ip -6 rule add iif wlan0 lookup 66 pref 66
ip -6 rule add oif wlan0 lookup 66 pref 66
ip -6 rule add iif tap-icvpn lookup 66 pref 66
ip -6 rule add oif tap-icvpn lookup 66 pref 66
ip -6 rule add iif wlan1 lookup 66 pref 66
ip -6 rule add oif wlan1 lookup 66 pref 66
ip -6 rule add iif tap-icvpn lookup 66 pref 66
ip -6 rule add oif tap-icvpn lookup 66 pref 66
" > /etc/rc.local
chmod 755 /etc/rc.local
cat /tmp/rc.local >> /etc/rc.local
8.3. PPtP configuration
network_pptp.uci
has additional interfaces for PPtP. Due to this separation,
PPtP interfaces are not created, when using the node-config opkg-package, only.
/etc/config/network_pptp.uci
# VPN - if pptp is used
# Servers are
# - omni.freifunk-koeln.de
# - yagi.freifunk-koeln.de
# Accounts: please mail vpn@freifunk-koeln.de
config interface 'vpn_pptp'
option disabled '1'
option proto 'pptp'
option server '195.54.164.202'
option username 'user'
option password 'password'
option ip4table '66'
option ip6table '66'
config interface 'vpn_pptp6'
option proto 'dhcpv6'
option ifname '@vpn_pptp'
option ip6table '66'
9. /etc/config/babeld
Babeld is used for routing. It uses the ad-hoc wifi interfaces. The optional interface tap-icvpn is included for Freifunk routing.
/freifunk/initial_configuration/babeld.uci
defines these options:package babeld
# Babel uses the mesh routing table (66) for import and export
# Routes are created with a low priority (2048); thus they're not considered local.
# By that, a default route on a (Open)VPN interface has higher precedence.
config general
option ipv6_subtrees 'true'
option export_table '66'
option import_table '66'
option kernel_priority '2048'
# Export all static routes from the freifunk tables
# This is the configured IPv4 and IPv6 network of the router
config filter 'redistribute_static'
option type 'redistribute'
option proto '4'
# Do not export local routes (LAN-IP, address, etc.)
config filter
option type 'redistribute'
option local 'true'
option action 'deny'
# Bind to both ad-hoc (802.11s) interfaces
config interface
option ifname 'wlan0'
option type 'wireless'
config interface
option ifname 'wlan1'
option type 'wireless'
# Optional fastd-interface for Freifunk Routing
config interface
option ifname 'tap-icvpn'
option type 'tunnel'
10. /etc/config/dhcp
OpenWRT uses dnsmasq and odhcpd to distribute prefixes. Node-config adds new definitions to. The OpenWRT wiki explains the DHCP options in use: [1, 2]
-
Hand out IPv4 address configured manually (DHCP)
-
Announce the IPv6 network configured manually (radv)
-
Re-distributing prefixes assigned automatically to the internet uplink (DHCPv6 PD).
-
Annoucing the manually assigned /64 range for SLAAC.
dhcp.uci
package dhcp
# A DHCP and radvd service is configured for the Freifunk interface
# The 254 address are used out the the manual prefix.
# For radvd, a default route is annouced. This enables routing freifunk traffic
# Subnet delegation is inactive. Subnets are delegated using the mesh interface, only
# Annoucing the configured /64 network is already part of /etc/network/interfaces.
# It doesn't hae to be configured, here
config dhcp 'freifunk'
option interface 'freifunk'
option start '2'
option limit '254'
option leasetime '10m'
option dhcpv6 'none'
option ra 'server'
option dhcp_option '6,46.182.19.48,146.185.167.43,80.241.218.68'
option ra_offlink '1'
option ra_default '1'
|
11. /etc/config/fastd
Fastd is a simple, decentralized vpn software. By default, fastd does neither switching nor routing. Both is handled by batman-adv and babel.
fastd.uci
package fastd
#fastd is used for Freifunk routing and supernode-stuff
# Test peer for Freifunk routing.
# Better: Setup your own peer and connect it to the icvpn usign BGP
config peer 'icvpn_test'
option remote 'ipv4 "5.9.31.99" port 11003'
option enabled '1'
option net 'backbone'
option key 'fa824f8d39adcb3ad6232660bda439020d3c2e61dd56466439fc66c0ee159b41'
# Network definition for Freifunk routing / disabled by default
config fastd 'backbone'
option enabled '0'
option syslog_level 'warn'
option mode 'tap'
option interface 'tap-icvpn'
option mtu '1280'
option forward '0'
option secure_handshakes '1'
list method 'salsa2012+umac'
# list bind 'any:10000' # Bind is done using shell
option secret 'generate'
# Template for Gluon supernodes / disabled by default
config fastd 'supernode'
option enabled '0'
option syslog_level 'warn'
option mode 'tap'
option interface 'tap-supernode'
option mtu '1312'
option forward '0'
option secure_handshakes '1'
list method 'salsa2012+umac'
list method 'null'
# list bind 'any:10001' # Bind is done using shell
option secret 'generate'
fastd is bound to the lan and lan interface, only. It makes no sense to use the mesh to tunnel mesh packages. Unfortunately, interfaces cannot be referenced by its OpenWRT name - thus the binding is done using shell.
fastd_binding.sh
#!/bin/sh
wan_if=$(uci get network.wan.ifname 2> /dev/null) # Ignore errors => No interface anyway
lan_if=$(uci get network.lan.ifname 2> /dev/null) # Ignore errors => No interface anyway
# Make sure, that fastd is using only lan and wan interfaces to avoid tunnel-in-tunnel situations
if [ $wan_if ];then
uci add_list fastd.backbone.bind="any:10000 interface \"$wan_if\""
uci add_list fastd.supernode.bind="any:10001 interface \"$wan_if\""
fi
if [ $lan_if ];then
uci add_list fastd.backbone.bind="any:10000 interface \"$lan_if\""
uci add_list fastd.supernode.bind="any:10001 interface \"$lan_if\""
fi
uci commit fastd
12. /etc/config/firewall & firewall.user
At quick glance, the firewall is used to seperate the mesh from other networks. Firewalling is done using the OpenWRT firewall and ebtables. See OpenWRT → Firewall for more information on OpenWRT’s firewalling options.
-
Creates a vpn and a freifunk zone. Forwarding from freifunk to vpn is allowed.
-
Exposes the fastd vpn on the WAN interface (meshing, roaming via vpn)
-
Makes the router accessible from the freifunk zone
-
Takes care of NAT internet traffic
-
Blocks broadcast / anycast traffic to the batman-adv mesh
Set a password on your router. It is accessible from the mesh network. |
package firewall
# The firewall seperates the mesh from other networkss such es wan or lan.
# Mind, that this configuration is not trusted
# your mesh router can still be compromies i.e. by exploiting babeld.
# This allows unfiltered access to your wan network.
# Allow: fastd from wan (roaming, meshing using vpn)
config rule
option name 'fastd'
option src 'wan'
option dest_port '10000'
option proto 'udp'
option target 'ACCEPT'
option family 'ipv4'
# Freifunk zone definition
# It has all the interfaces used for mesh routing (babel) and the central freifunk brdige.
config zone 'freifunk'
option forward 'ACCEPT'
option output 'ACCEPT'
option input 'REJECT'
option name 'freifunk'
list network 'freifunk'
list network 'babel_mesh'
list network 'babel_mesh5'
list network 'fastd'
option mtu_fix '1'
# In the freifunk zone, the router can be access by
# 1st Babel
config rule
option name 'Babel'
option src 'freifunk'
option proto 'udp'
option dest_port '6696'
option limit '1000/sec'
option target 'ACCEPT'
# 2nd IGMP
config rule
option name 'Allow IGMP (Freifunk)'
option src 'freifunk'
option proto 'igmp'
option family 'ipv4'
option target 'ACCEPT'
# 3rd ICMP
config rule
option name 'Allow ICMP (Freifunk)'
option src 'freifunk'
option proto 'icmp'
option family 'ipv4'
option target 'ACCEPT'
# 4th DHCP
config rule
option name 'Allow DHCP request (Freifunk)'
option src 'freifunk'
option dest_port '67-68'
option proto 'udp'
option target 'ACCEPT'
option family 'ipv4'
# 5th ICMP v6
config rule
option name 'Allow-ICMPv6-Input (Freifunk)'
option src 'freifunk'
option proto 'icmp'
option limit '1000/sec'
option family 'ipv6'
option target 'ACCEPT'
# 6th SSH (Mind setting a password)
config rule
option name 'Allow SSH (Freifunk)'
option src 'freifunk'
option dest_port '22'
option proto 'tcp'
option target 'ACCEPT'
# Internet exit through VPNs need another zone, since it has to by masquerade
config zone
option forward 'ACCEPT'
option output 'ACCEPT'
option input 'REJECT'
option name 'vpn'
option network 'vpn vpn6 vpn_pptp vpn_pptp6'
option masq '1'
option mtu_fix '1'
# In the VPN zone, some incoming traffic is allowed
# 1st ICMPv6 incoming
config rule
option name 'Allow-ICMPv6-Input (VPN)'
option src 'vpn'
option proto 'icmp'
option limit '1000/sec'
option family 'ipv6'
option target 'ACCEPT'
# 1st ICMPv6 outgoing
config rule
option name 'Allow-ICMPv6-Output (VPN)'
option dest 'vpn'
option proto 'icmp'
option limit '1000/sec'
option family 'ipv6'
option target 'ACCEPT'
# This allows accessing the internet to a vpn tunnel
config forwarding 'freifunk_internet'
option dest 'vpn'
option src 'freifunk'
# To allow direct access, change it to:
# config forwarding 'freifunk_internet'
# option dest 'wan'
# option src 'freifunk'
# Mind handling abuse
# To prevent direct exit traffic accessing your uplink network,
# RFC1918 and ULA addresses are blocked.
# Please mind, that accessing public IP addresses is allowed, still.
config rule
option name 'Do not forward freifunk traffic to RFC1918 address in WAN zone'
option src 'freifunk'
option dest 'wan'
list dest_ip '10.0.0.0/8'
list dest_ip '192.168.0.0/16'
list dest_ip '172.16.0.0/12'
option family 'ipv4'
option target 'REJECT'
option proto 'all'
config rule
option name 'Do not forward freifunk traffic to local ipv6-addresses in WAN zone'
option src 'freifunk'
option dest 'wan'
list dest_ip 'fc00::/7'
list dest_ip 'fec0::/10'
option family 'ipv6'
option target 'REJECT'
option proto 'all'
Broadcast / anycast traffic is blocked using ebtables. ebtables rules are not
exposed via uci. firewall.sh
takes care of adding this rules to the firewall.user
script.
#!/bin/sh
# ebtables Multicast-filter - not exposed to uci
# reject multicast / broadcast within the batman-adv mesh
# allow DHCP and ARP - it is translated into unicast
echo "
ebtables -F
ebtables -A FORWARD -p ARP -j ACCEPT
ebtables -A FORWARD -p IPv4 --ip-protocol udp --ip-destination-port 67:68 -j ACCEPT
ebtables -A FORWARD -d Multicast -j DROP
#" > /etc/firewall.user
For policy routing, additional ip-rules are added to |
13. /etc/config/openvpn
OpenVPN is used to tunnel internet traffic. Using external configuration files, the different providers are referenced, only.
package openvpn
# OpenVPN-configuration for tunnel providers
# Beispiel fuer mullvad - hier enabled (vgl. https://mullvad.net/en/)
config openvpn 'mullvad'
option enabled '0'
option config '/lib/freifunk/vpn/mullvad/mullvad.conf'
# Freifunk-KBU Exit-VPN
# More information:
# - https://kbu.freifunk.net/wiki/vpn-exit
config openvpn 'freifunk_kbu'
option enabled '0'
option config '/lib/freifunk/vpn/freifunk_kbu/client.conf'
# yanosz' Freifunk-Exit-VPN
# Used for testing
# Please freifunk@yanosz.net for access.
config openvpn 'yanosz'
option enabled '0'
option config '/lib/freifunk/vpn/yanosz/client.conf'
Here is an example for an external configuration. It can be used as a template for other providers. Refer to https://openvpn.net/index.php/open-source/documentation.html [the OpenVPn website] for information on different OpenVPN options.
# yanosz Freifunk-Exit-VPN
# used for testing
# Plase mail freifunk@yanosz.net for access
# Path - adjust if needed
cert freifunk@yanosz.net.crt
key freifunk@yanosz.net.key
# OpenVPN must not configure routing - it cannot use a different routing table such as 66
# Routes are set using a custom scrip
route-nopull
up /lib/freifunk/vpn/up.sh
remote freifunk-vpn.yanosz.net 1194
proto udp
# As an alternative
#remote freifunk-vpn.yanosz.net 443
#proto tcp
# OpenVPN-specifics
client # Its a client
dev vpn-nat
dev-type tun # Keep aligned with /etc/config/network
cipher AES-256-CBC # 256-Bit AES encryption is used
resolv-retry infinite # Try to establish a connection continuously
nobind
persist-key
persist-tun
comp-lzo
remote-cert-tls server
ping-restart 60 # 60 Sekunden Ping Restart Timer
script-security 2 # Scripts - needed to execute up.sh
ca ca.crt
ping 10
link-mtu 1350 # Small MTU (tunneling through adsl lines has some offset)
When setting up a new vpn provider, some settings need to be added to the provider’s configuration:
|
Advanced Topics
You made a long way. The documentation has many complex details and its quite easy to get lost. Anyway, you made it :-).
This chapter focuses on advanced topics. It explains how to use node-config to build packages, create a firmware and to do configuration management.
Illustrating underlaying concepts such as multihomming, roaming an Freifunk routing is also part of this chapter.
14. Building node-config
Node-config uses different Makefiles to generate packages and documentation. When building node-config, architecture independent opkg packages ("all") are generated using the OpenWRT SDSK.
Also, this chapter describes the underlaying network architecture and propose working methods for node-config.
14.1. Makefiles
Node-config is built using Makefiles. The project contains two Makefiles
-
./Makefile
is the global makefile. Packages and Documentation is generated usingmake dist
. Have a look at the makefile for other targets -
./lede_build/node-config/Makefile
defines the actual opkg packages. By default, node-config is split innode-config
(base part),node-config-openvpn
(openvpn configuration and dependencies) andnode-config-pptp
(pptp configuration and dependencies).
15. Generating a OpenWRT package repository (feed)
Running make dist
creates a opkg package repository (feed) at dist/feed
.
To use this repository on an OpenWRT router, all packages must be signed using a public/private keypair.
The private key is used to create a signature and has to be present on the router.
Keys are generating using usign
, that is part of the OpenWRT SDK.
./sdk_home$ staging_dir/host/bin/usign -G -s secret.key -p public.key
./sdk_home$ cat public.key
untrusted comment: public key 9cf140f9fda134d8
RWSc8UD5/aE02AM7y99Y39xfadMna1qpT0sdFtVLU80I508fYqW+tXLG
./sdk_home$ mv public.key 9cf140f9fda134d8 # Change accordingly.
In this example, the key id is 9cf140f9fda134d8
. Thus the file public.key
has to be renamed to
9cf140f9fda134d8
. To use the key on OpenWRT, it has to be placed at /etc/opkg/keys/9cf140f9fda134d8
.
$ make dist BUILD_KEY=/full/path/to/secret.key
$ cat dist/feed/Packages.sig
untrusted comment: signed by key 9cf140f9fda134d8
RWSc8UD5/aE02GlvkPCIjUvvX9QA0J8a34ONvj2FWcXOZXdF/WTpxyOyvaxwfwPqwvpb14O8Au7SWapAwWnk9LjJ6XFBozfPDwg=
Copy dist/feed
to a webserver and place a reference at /etc/opkg/feeds.conf
.
Consider make repository accessibly via http and https: opkg doesn’t support SSL/TLS - the imagebuilder does not require the key to present but supports TLS. |
16. A Graphical User Interface (GUI).
A Freifung-styled AngularJS based WebUI is available at https://github.com/yanosz/firmware-wizard-frontend. It’s still under active development. Contributors welcome :-).
17. Creating Firmware & Configuration Management
Although node-config is not focussing on creating a firmware blob, OpenWRT’s imagebuilder. can be used for doing so.
$ wget https://downloads.openwrt.org/releases/18.06.1/targets/ar71xx/generic/openwrt-imagebuilder-18.06.1-ar71xx-generic.Linux-x86_64.tar.xz
$ tar xf openwrt-imagebuilder-18.06.1-ar71xx-generic.Linux-x86_64.tar.xz
$ cd openwrt-imagebuilder-18.06.1-ar71xx-generic.Linux-x86_64
$ echo "src/gz nodeconfig https://kbu.freifunk.net/files/node-config/feed >> repositories.conf
$ make image PROFILE="Default" PACKAGES="node-config node-config-openvpn ip-full luci-ssl"
A gitlab-ci job building firmware including the GUI is available at https://git.kbu.freifunk.net/yanosz/node-config-feed |
TBD: Configuration management using mesh testbed generator
18. Underlaying concepts
18.1. Roaming
Roaming concerns clients moving from one accesspoint to another. To keep all connections alive, traffic must be redirected.
Roaming from A to B, the wifi association is updated: In the beginning, all data is transmitted to node A. When changing the association, data goes via B instead. This is illustrated in Figure 2. Due to node A and B using the same ESSID, the client interfaces is not reset.
In this scenario, packets need to be handled by a different nodes: While node A handle’s the clients packets in the beginning, node B is responsible in the end. This is, where things get messy: Network state needs to be updated. IP-packets need to find a new way. However, some ideas exists:
-
Creating a large, ethernet segment using batman-adv: As done in classical ethernet networks, a client’s location is updated using broadcast / multicast continuously behind the scenes. In this a flat, MAC-based address scheme, routes cannot be aggregated. In Freifunk communities, these networks are VPN based and scale up to 1000 ~ 2000 nodes.
-
Update IP routing on roaming: Instead of creating a large ethernet segment, the network is split into one segment per node. One dedicated subnet is assigned per segment. IP-Packets are routed between those segments using traditional IP-routing. Whenever a client roams, a host route is added to the routing table. This approach may reduce the size of the routing table. But in order to so, each node needs to know all IP-addresses used by clients roaming into its segment. Getting only a mac address from the wifi association, this task is very challenging. l3roamd tries to go this way, but it is not ready for production, yet.
-
Mobile-IP like approaches. In Mobile IP traffic is handled by a home node and passed along the network. It takes care of maintaining reachability information and passing packets to its clients. As a downside, routing through a home node may increases the forwarding path. In addition, management traffic for both batman-adv and babel has to be handled.
Combining babel and batman-adv, node-config includes configuration for a mobile IP like system, while not being restricted to it. Its functionality is illustrated in the next sections:
At quick glance, using routing two routing protocols (babel and batman-adv) at the same-time seems counter-intuitive: It’s just duplicating the management effort, isn’t it? Of course, an ideal mesh protocol would take care of routing and roaming; propagating reachability information on MAC and IP-addresses alongside. Unfortunately, no such protocol exist.
In an Mobile IP like setup, the forwarding path doesn’t increase necessarily. In order to prevent source ip spoofing and to maintain NAT state in a multi homed network, external traffic is routed via fixed "home-ish" gateway node in any situation. |
18.1.1. Roaming in node-config using IPv4
Figure 2 illustrates roaming using IPv4. A client roams from node A to B. The traffic-flow is green, while network connections are red.
The batman-adv mesh cloud connects all segments in transmission range. It acts as a huge network switch.
The client is using 10.0.1.42 from A’s dhcp range. By that, node A is the home node of the client. (Read this as: 10.0.1.1 is set a gateway using dhcp).
When roaming, node A is responsible for handling all the traffic. The client reaches node A (10.0.1.1) using the batman-adv cloud (and vice versa). Having batmn-adv’s distributed ARP table enabled, ARP broadcasts won’t hurt the mesh. Thus - as in classical ethernet - both are talking ARP using their MAC-addresses.
Keep in mind, that ethernet segments are limited by the transmission range of the nodes. There is no large ethernet segments connecting all nodes using a VPN.
18.1.2. Roaming in node-config using IPv6
For IPv6 the situation is more complex. In contrast to IPv4, clients have multiple addresses and gateways provided by the radv-protocol.
In node-config, a distinct default route is announced by every router (distinct: unique link local address). When a clients roams to a different node, it has two default routes, at least. This is illustrated in figure 4.
As before, the clients roams from node A to B. Before connecting to node B it is reachable at fd00:1::42. This address is allocated using slaac in node A’s segment. Node A is used for routing (route #1)
When moving to node B, the client receives an additional route (route #2) and address (not shown) from the node B. Having two default routes, the client can access other networks via node A (route #1) and node B (route #2).
-
route #1:
-
next-hop: link local address of node A.
-
When selected, the client tries to reach node A by its MAC-address.
-
mac-address: reachable via batman-adv
-
-
route #2:
-
next-hop: link local address of node B
-
mac-address: based in the infrastructure network (no batman-adv).
-
Mind, that the traffic (inbound vs. outbound) is slightly asymmetric.
-
Incoming traffic arrives via node A, only. To reach the client, it is send trough the batman-adv cloud.
-
Outgoing traffic is somewhat asymmetric:
-
If the client chooses the old route, traffic is reaching node A through the batman-adv cloud
-
If the client chooses the new route, traffic may by routed via node A using babel; external traffic (i.e. internet) always leaves the mesh via node A due to source specific routing.
-
Although babel and batman-adv are operating in the same topology, they use different metrics. Thus babel and batman-adv may choose different paths from B to A. |
Have in mind, that node-config blocks all multicast traffic in batman-adv including IPv6 Neighbor Solicitation (NS). By doing so, Node A has no chance to discover the client’s mac address after roaming. Node config assumes:
-
All MAC addresses are cached while relevant.
-
Address collisions won’t occur, since nodes have just a few clients.
-
A client learning a routers mac from a radv-message doesn’t need NS to find the correspondig router at all time.
18.1.3. Roaming in wifi range vs. planned roaming
If nodes are in in transmission range, roaming will be easy: packets from B to A are sent using wifi, after the client moved from A to B. This seems to be realistic: When a client roams, it is connected to the wifi all time long: If the signal is lost, the network interface will loose its association and the connection is reset.
Unfortunately, this doesn’t work out in any case:
-
There’re obstacles around (i.e. walls) shadowing one node: one node won’t be able to reach the other - packets will get lost.
-
Retransmitting packets uses twice the airtime (at least). This reduces the overall performance.
|
In these situations you can offload roaming traffic i.e. by using wired or directed links. In many situations, its good to use a fastd based vpn (TODO yanosz: add a fastd example configuration for offloading in node-config). While fastd is easy to setup and fits for many situations, other technolgies (ethernet, l2tp) provide a better performance:
-
Choose a medium for off-loading (i.e. ethernet, p2p-wifi, l2tp).
-
Create a corresponding OpenWRT configuration
-
All all interfaces to babel in
/etc/config/babel
-
Add all interfaces to the freifunk firewall-zone in
/etc/config/firewall
-
Add policy-routing for these interfaces using table
66
in/etc/firewall.user
-
Add a batman-adv mesh definition for all interfaces in
/etc/config/network
. -
Modify
/lib/freifunk/set_ip.sh
to set and IPv4-address (/32) on all related interfaces, execute it, reboot the node.
Unfortunately, policy routing and firewalling makes it very complex to add a new link for offloading. This is the downside of having a Freifunk-style exit-vpn using an arbitrary provider. When removing this functionality, you can skip steps 4 and 5. Using fastd for all links somewhat simplifies this situation, because - unlike l2tp - only one tap interface definition is needed for any number offloading peers.
Have in mind:
|
18.2. “Multihoming” & Prefix Delegation
A network run by node-config may have multiple internet uplinks. Typically, internet uplinks are provided by different providers using different IPv4 and IPv6 networks.
This is illustrated in figure 5. By design, each node acts as a router:
-
It routes packets using babel
-
It runs in batman-adv gateway mode, handing out IP addresses.
Routing packets internally is easy: Having distinct non-overlapping IPv4 and IPv6 networks per node, every network is homed at an unique node. Each node announces its prefixes using babel - packets can be routed. If a node is connected to the internet (uplink), it will announce a default route in addition.
Originally, the term multihoming refers to a situation in BGP: A private autonomous system (AS) announces its prefix via different upstream providers. Having the private AS-number removed from the path, all networks appear to be originating from all providers; hence they are home to multiple places. |
18.2.1. IPv4 & Network Address Translation (NAT)
By default, node-config uses private IPv4 space. To access the internet, network addresses need to be translated (NAT).
In figure 6 node A and node B are directly connected to the internet. Node A is using 192.0.2.1 - Node B is using 203.0.113.1. In node-config, both A and B take care of NAT: When leaving the mesh network, the sender address is changed to 192.0.2.1 (203.0.113.1 resp.).
This design assumes, that the route selection in babel is stable: From the perspective of node D, both A and B have usable default routes; the choice is arbitrary. But if D’s selection changes (i.e. from A to B), the NAT will break: By turning over, the sender address switches from 192.0.2.1 to 203.0.113.1. This breaks all the TCP session of all clients at D.
Babeld’s stability is defined by the half-time parameter - see man babeld for details.
18.2.2. IPv6, source specific routing & Prefix Delegation
The situation is different for IPv6. Instead of translating IP-addresses, routers with internet connectivity provide public address space to all other routers.
IPv6 is probably not mature, yet. Altough, node-config only use OpenWRT’s core components and follows IPv6’s best practices by using prefix delegation, some details are likely to be broken. In addition, node-config’s IPv6 configuration is largely untested: Only a few vpn providers have support IPv6 prefix delegation. |
Address space is assigned using DHCP v6 prefix delegation. See
rfc3633 for details. In figure 7, 2001:DB8:AAAA::/56
is assigned to
node A by its provider. Node B got 2001:DB8:BBBB::/56
.
To use these networks, corresponding addresses must be assigned to clients at nodes C,D,E and F.
In order to do so, at least one /64
network must be assigned to each node.
Node-config is using the ad-hoc (or 802.11s) network for prefix delegation. Here’s an example:
-
Node C is connected to A. It gets
2001:DB8:AAAA:1::/64
-
Node D is connected to A and B. It gets
2001:DB8:AAAA:2::/64
and2001:DB8:BBBB:1::/64
-
Node E is connectd to B. It gets
2001:DB8:BBBB:2::/64
Mind, that this configuration is dynamic: C,D and E may choose to request more than one prefix. In addition,
they can request a larger subnet (i.e. /60
) for redistribution.
However, there’s catch: If a client uses 2001:DB8:AAAA:2::42
, it must use node A
to access the internet - node B’s provider will probably reject the packet due to address spoofing
(wikipedia). Here source-specific routing comes
into action. Node A and B announce a default route for their range, only. Babel takes care of using the
correct route
Most internet protocols (i.e. BGP) follow the destination based forwarding paradigm: The route of a packet is determined by its destination address, only. Source routing is an alternative to destination based forwarding. Here, the path is defined at the sender. This approach is done by some mesh protocols, implemented in IPv4, but hardly used. Source specific routing somewhat follows the destination based forwarding paradigm. The route is determined by the sender address, only. In addition, routes are restricted to a specified source range, limiting the set for destination based lookups. Babel is using source specific routing, to comply with the destination based forwarding paradigm, while taking care of multiple IPv6 networks in the same mesh. It’s sad, that most slaac-implemtations do not restrict routes like source specific routing does. |
Unfortunately, node-config’s IPv6 functionality is hardly tested.
-
What happens, if node A crashes?
-
Will D detect this?
-
Will D stop announcing
2001:DB8:AAAA:1::/64
? -
Will D’s client use
2001:DB8:BBBB:2::/64
, only?
-
-
Is DHCPv6 proxying better than redistribution?
-
What’s a good redistribution strategy? (density?)
-
A way out: Static IPv6 assignments.
As an alternative to prefix delegation you can assign IPv6 networks, statically.
By providing a public IPv6-network instead of an ULA-network (i.e. when using set_ip.sh
).
This can be done using provider independent (PI) address space or space assigned by large tunnel providers (i.e. https://tunnelbroker.net).
While this is fine for networks under a central administration, the Freifunk philosophy rejects the idea of a central administration or uplink. See Design considerations for details.
A different way out? Network Prefix Translation
Network prefix translation can be used as an alternative to prefix delegation. Instead of
handing out public address space, ULA addresses are translated to access the internet.
(i.e. from fdc3:337e:00c0:3f04::42
to 2001:DB8:AAAA:5271::42
).
This is done on all border routers with IPv6 connectivity (i.e. nodes A and B).
Using ULA addresses removes the necessity of maintaining state for network delegations (mind the dragons of Prefix Delegation). Unfortunately, this approach has some drawbacks
-
End-to-end addressing is a fundamental building block for IPv6 networks. Address translation is violating this paradigm. Expect issues with protocols expecting compliance.
-
As in IPv4 (c.f. figure 5) changing the path also changes the sender address and resets all TCP connections. Unlike IPv4, you cannot set a fixed default gateway using DHCPv6 (DHCPv6 Route Options never made it an internet standard), thus we have to consider roaming, again:
-
You can live with it
-
You can translate all addresses to a statically assigned IPv6 prefix - but then you can do static IPv6 assignments anyway. There’s no need to translate addresses, anymore.
-
You can use DHCPv6 Prefix Delegation for ULA addresses and babel’s source specific routing. While this looks attractive in the first place (unexpected changes in external delegations won’t ruin your day), the dragons of Prefix Delegation will still be there
(… what happens, if node A crashes …)
-
19. Freifunk Networking
Let’s have a look at Freifunk: https://freifunk.net has a good introduction into the Freifunk community, its motivation, goals and structure.
In contrast to a green-field mesh vpn, integration into existing community networks is an issue - especially, if you want to use your router in an existing Freifunk network. As of today, most Freifunk networks are based on Gluon or connect via the Intercity-VPN (ICVPN).
19.1. Gluon integration / migration
Node-config was developed with Gluon networks in mind. Also, it tries to overcome some limitations of gluon networks. See <<#_Design considerations>> for details.
In gluon networks, node-config can be used as a node, supernode, or vpn-offloader. Although all options are explained at this section, doing so somewhat looses the focus of the points node-config tries to address.
Probably the best way to integrate a node-config router into a Gluon network is to operate it side-by-side.
19.2. Side-by-side operation
In side-by-side operation a node-config router is using the same SSIDs meshing on layer-2.
To so do edit /etc/config/wireless
according to your Freifunk community.
It also interesting, to connect all node-config routers and supernodes using a routed vpn speaking babel.
/etc/config/fastd
provides a icvpn template for doing so. This allows end-to-end adressing.
Consider planned romaing (i.e. fastd from node-config to supernode), if and only if a node-config router is in the vicinity of gluon node. The load will be challanging. See <<#_Design_considerations>> for details. |
19.3. Gluon Supernode
Node-config’s internals are very similar to a gluon supernode: It speeks batman-adv over fastd and provides DHCP as well as routing and ravd services. In fact, some supernodes are connected using a backbone vpn using babel. There’re some smaller differences, still.
Most OpenWRT routers probably lack the horsepower needed for a supernode - even for a mediocre sized network. |
-
Gluon supernodes to not speak babel to other (non-super)-nodes in the mesh.
-
Usually, a DHCP pool of 250 addresses is not enough for a freifunk network.
Node-config contains a fastd supernode template. Enabling it goes like this:
uci set fastd.supernode.enabled=1
uci commit
/etc/init.d/fastd restart
/etc/init.d/fastd show_key supernode
By that, a fastd instance is started on 10001/udp
. It’s accessible using the WAN and LAN interfaces.
fastd’s public key is printing using the show_key
command.
It can to be integrated into the Gluon site configuration - for more information on configuring fastd
see https://fastd.readthedocs.io/en/v17/manual/config.html
To increase the DHCP pool, you need to change one line in /etc/config/network and /etc/config/dhcp.
config interface 'freifunk'
# .. some other options ..
option netmask '255.255.0.0'
config dhcp 'freifunk'
# .. some other options ..
option limit '10000'
19.4. Gluon node / VPN-Offloader
A gluon node is very lean: It connects to a supernode using fastd and speaks batman-adv. It’s not running any other service (i.e. babel, dhcp, routing).
Technically, there’s hardly any difference between a gluon node and a vpn-offloader. Boiling it down, a vpn-offloader is a node also accepting incoming fastd connections.
Typically, vpn-offloaders are more powerful gluon nodes, deployed at large sites. Here, only the vpn-offloader maintains a connection to the supernode. All other nodes connect to the offloader instead. Having only one connection to the supernode (instead of one connection per node), brodcast / multicast traffic is sent only once. By that, traffic is reduced.
-
Enable the supernode fastd instance
uci set fastd.supernode.enabled=1
-
Disable the batman-adv gateway mode
uci set batman-adv.bat0.gw_mode='client'
-
Disable babel:
/etc/init.d/babeld disable
-
Disable DHCP:
uci set dhcp.freifunk.ignore=1
-
Commit & restart:
uci commit
-
Change SSID and channel in
/etc/config/wireless
according to your Freifunk community.
Reboot the router, when you’re done.
When running a node instead of an offloader, mind firewalling
the fastd-instance by commenting out the correspondig rule in /etc/config/firewall
.
19.5. ICVPN routing
The Intercity-VPN network (ICVPN) is a tinc and BGP based network for connecting all Freifunk communities. See https://wiki.freifunk.net/IC-VPN (german) for details.
Unfortunately, the design of ICVPN makes it almost impossible to connect using a small SoHo-router, only. The configuration (BGP, DNS) is generated using python scripts operating on a cloned git repository. Way to much for a small node. Thus ICVPN connectivity using DNS and BGP is outside the scope of node-config.
Looking at the big picture, BGP and DNS can be handeled on a different platform (i.e. RaPi running Debian), exposing its connectivity using babel. Then, node-config can:
-
Use routes learned via babel to connecting to ICPN hosts.
-
Use a IPv6 anycast address for DNS.
Unfortunately, the Freifunk community rejected the idea of a DNS-TLD-naming convention, thus delegations for all Freifunk DNS TLDs must be configured individually. Generating a suitable dnsmasq-configuration is also part of the pyhton scripts provided by ICVPN. This manual won’t go into detail here. See https://github.com/freifunk/icvpn or https://wiki.freifunk.net/DNS for more information.
IPv4 is futile. Use IPv6, only. |
Still, node-config has a fastd-instance for ICVPN routing. It’s integrated into babel but not into batman-adv. In addition, there’s a test peer providing basic ICVPN connectivity.
uci set fastd.backbone.enabled=1
uci commit fastd
/etc/init.d/fastd restart
20. Design considerations
Up to now, we were looking technical aspects. That’s ok. You’re reading a technical documentation and - no regrets - it’s supposed to be like that. On the other hand, most design decisions are based on specific goals or requirements. Here, at the end, it’s time to connect the dots. These requirements are key to node-configs design:
-
You don’t need any servers: Some Freifunk network designs promote data center based servers (supernodes) to provide basic network functionality (i.e. routing, dhcp). This needs extra funding, requires a reliable internet connection as well as a data center and introduces additional complexity. As a requirement for node-config, basic functionality has to be provided by the nodes.
-
Use vanilla OpenWRT releases: Many community networks are based on custom OpenWRT builds or forks. To start a network, OpenWRT has to be compiled or forked at first. Usually, only a few people know how to maintain or compile the software needed to run the network. Node-config is required to use OpenWRT as-it-is; using released images and packages, only.
-
Share your local internet connection: Freifunk and other networks are built with the idea of having one or many internet gateways providing connectivity. Unfortunately, many networks depend on an external infrastructure (i.e. a fixed vpn provider). For node-config, the need for a designated vpn provider has to be eliminated. Node-config must allow direct internet sharing or using an arbitrary vpn provider.
-
Wifi & OpenWRT configuration is all you need to know: Introducing servers or operating vpn providers requires additional knowledge in a community. For instance, supernodes require management using ansible or puppet, connecting to autonomous systems (AS) (i.e. Freifunk Rheinland e.V.) via vpn puts the Border Gateway Protocol (BGP) on the table. In its core, that knowledge is outside of running wifi mesh networks and raises the entrance barrier. Using node-config must not require any additional knowledge (except OpenWRT configuration and wifi).
-
Overcoming scaling limitations seen in Gluon based networks. Many proposed Gluon design scale up to 1000 ~ 2000 nodes per mesh. Basically, this is due to broadcast / anycast and batman-adv management traffic sent to all nodes. Roaming management traffic is distributed across regions without any reasonable wifi coverage. Node-config is required to scale better by integrating hierarchical routing and to limit roaming management traffic to definable regions.
-
Be decentralized - no administration authority. Node-config is desinged to implement decentralisation (c.f. Hacker Ethic (wikipedia)). It is required, that no administration authority governs the network. Node-config is required to:
-
Eliminate the need for network administrators (i.e. for servers or BGP routers)
-
Empower people by providing a simple and accessible design as well as documentation.
-
Lower the entrance barrier (funding, infrastructure, know-how) for new communities.
-