Generic Freemesh Gateway

From FreeMesh
Jump to: navigation, search

Generic Installation of a Gateway for FreeMesh (FreiFunk)

This is a generic configuration that was put together for the use in Freifunk Flensburg, Freemesh Denmark and Freemesh Ireland.


  • min. 2 cores with good thread performance
  • min. 512 MB RAM
  • min. 10 GB HDD
  • approx. 5 TB/Month traffic allowance is a good start.
  • you have to be able to modify the kernel on your server, so OpenVZ or the likes won't work
  • min. 100 Mbit/s connectivity is recommended
  • recommended is also a VPN provider for tunneling the traffic out

Define your Settings

For your Mesh Network, you need some settings, that are unique for your community. So choose fitting settings for your community and this gateway first:

FREEMESH_VPN_NUMBER=1                                    # your vpns should be numbered
FREEMESH_NAME="Freemesh Alpha Centauri"
FREEMESH_DOMAIN_NAME=$FREEMESH_HOSTNAME.$FREEMESH_DOMAIN # this will result in the full domainname your gateway will be reacheable from the outside
FREEMESH_TLD=ffac                                        # your mesh-top level domain inside the mesh net
FREEMESH_IP4PREFIX=10.X                                  # choose a free prefix from ICVPN, for example 10.217 seems to be free:
FREEMESH_IP6PREFIX="fdec:XXXX:XXXX"                      #choose an ULA ipv6 prefix
FREEMESH_IPV4="$FREEMESH_IP4PREFIX/19"                   # a slash 19 subnet should suffice
FREEMESH_NETMASK="255.255.X.X"                           # set this according to $FREEMESH_IPV4
FREEMESH_DHCP_NETMASK="255.255.Y.X"                      # should be smaller than $FREEMESH_NETMASK, so you have some IPs reserved that are not given out by DHCP for fixed services
FREEMESH_MTU="1280"                                      # this is the smallest possible MTU to get around some problems with cable-providers
FREEMESH_PUBLIC_IPV4=                             # the IP that your gateway will be accessible from the outside internet


1. Install a minimal Debian jessie

  • make sure to set the hostname and domainname:
echo $FREEMESH_HOSTNAME > /etc/hostname
  • pick a secure root password.
  • create a regular user on the host, then limit Root from being able to log in via ssh

Update all

apt update
apt upgrade
apt-get update 
apt-get upgrade

2. Stuff that is needed

apt-get install screen htop iftop traceroute mtr-tiny mc speedtest-cli openvpn bash-completion nano ca-certificates haveged bridge-utils ntp unbound isc-dhcp-server radvd iptables-persistent apt-transport-https postfix pdns-server sudo git apt-transport-https

choose all default but postfix, choose "local only" there

3. B.A.T.M.A.N. and fastd

add jessie-backports to your /etc/apt/sources.list, then

apt-get install batctl fastd
# use 'apt-get -y --force-yes' if the key is outdated

The following section is only needed, if you need the repository

# echo "deb sid main" >>/etc/apt/sources.list
# gpg --keyserver --recv-key  16EF3F64CB201D9Coption
# gpg -a --export 16EF3F64CB201D9C | apt-key add -

The following section is only needed, if you need to downgrade to batman 14

# modinfo batman-adv
# apt-get install batman-adv-dkms
# dkms remove batman-adv/2013.4.0 --all
# dkms --force install batman-adv/2013.4.0
# modprobe batman-adv # (if the wrong version is loaded "rmmod batman-adv" and then repeat the dkms commands)
# dmesg # (check, to see, that you have the correct version loaded)

This is needed for any version

add batman-adv to your /etc/modules to autoload it on boot and activate it:

echo "batman-adv" >> /etc/modules
modprobe batman-adv

create the directory for your fastd peers:

mkdir -p /etc/fastd/vpn/peers

create the keys for fastd:

fastd --generate-key > /root/

Backup the key pair `/root/` in a safe place. This will be needed both for the server and for the image builds.

create the .conf for fastd:

nano /etc/fastd/vpn/fastd.conf

insert in your fastd.conf:

log to syslog level debug;
bind any:10000 interface "eth0";
method "salsa2012+umac";
mtu 1280;
include "secret.conf";  # include the secret.conf with your private secret key from the /root/ 
include peers from "peers";     # your peerlist with the other gateways
on verify "true";   # this allows any unknown node to connect to your fastd
on up "
  /sbin/ifup bat0
  /bin/ip link set dev tap0 address 00:00:ff:f1:f0:01
  /bin/ip link set dev tap0 up

create the secret.conf for your private secret key:

nano /etc/fastd/vpn/secret.conf

insert your private secret key from the /root/ in the secret.conf:

secret "$your_private_secret_key_from_the_/root/";

For the gateway to be able to connect to the other gateways and nodes known in the network, you need to get a bunch of files with the public keys for these. For Freifunk Nord for example, this looks like this:

git clone /etc/fastd/vpn/peers

reload fastd without quitting:

killall -HUP fastd

if it says "no process found", its because you just installed it and it doesn't run, so just start it:

service fastd start

Regularly update the peers via cron.

nano /etc/fastd/

# hop into correct directory to avoid cron pwd sucks
cd $(dirname $0)

# function to get the current sha-1
getCurrentVersion() {
  git log --format=format:%H -1

# get sha-1 before pull

git pull -q

# get sha-1 after pull

# if sha-1 changed, make fastd reload the keys
if [ "$revision_current" != "$revision_new" ]
 kill -HUP $(pidof fastd)

make the script executable

chmod +x /etc/fastd/

and add these lines in cron with

sudo crontab -e
# Regularly update the fastd peers
*/5 * * * * /etc/fastd/

4. Networking

Edit the file /etc/sysctl.conf and find the section

# Uncomment the next line to enable packet forwarding for IPv4

# Uncomment the next line to enable packet forwarding for IPv6
#  Enabling this option disables Stateless Address Autoconfiguration
#  based on Router Advertisements for this host

The two forwarding rules will be commented out, so you need to remove the # in front of them

Edit the file /etc/network/interfaces:

- Everything above the line "FREEMESH" is the config from your hoster, don't made any changes here except adding the #Batman-Part on top of the interfaces. On some hosters, there are no addresses in this part, because they are using a dhcp, but thats fine, you don't have to change that.

- After the line "FREEMESH" is the config for your Freifunk Community. Add the parts from here and edit it with your settings.

# The loopback network interface
    auto lo
iface lo inet loopback

# Batman
    auto br-$FREEMESH_TLD
    allow-hotplug bat0

# The primary network interface
auto eth0
iface eth0 inet static
    address [your public ipv4]  # don't change
    netmask [your public netmask]  # don't change
    gateway [your public gateway]  # don't change
    dns-nameservers [your dns servers]  # don't change

iface eth0 inet6 static
    address [your public ipv6]  # don't change
    netmask [your public ipv6 netmask]  # don't change
    gateway [your public ipv6 gateway]  # don't change

#  HOSTER: Everything above this line is the config from your hoster
# <----------------------------------------------------------------------
#  FREEMESH: Everything after this line is the config for your community

# Batman
    up /sbin/brctl addbr br-$FREEMESH_TLD

iface br-$FREEMESH_TLD inet static
    address $FREEMESH_GW_IP4
    netmask $FREEMESH_NETMASK # for example
    bridge-ports none

iface br-$FREEMESH_TLD inet6 static
    address $FREEMESH_IPV6
    netmask 64

# batman interface
iface bat0 inet6 manual
   pre-up /usr/sbin/batctl if add tap0
   up /bin/ip link set dev bat0 up
   post-up /sbin/brctl addif br-$FREEMESH_TLD bat0
   post-up /usr/sbin/batctl it 10000
   post-up /usr/sbin/batctl gw_mode server
   post-up /sbin/ip rule add from all fwmark 0x1 table 42
   post-up /sbin/ip -6 rule add from all fwmark 0x1 table 42
   pre-down /sbin/brctl delif br-$FREEMESH_TLD bat0 || true
   down /bin/ip link set dev bat0 down

   # this is for adding the gateway to the map later, not necessarily necessary.
   # post-up start-stop-daemon -b --start --exec /usr/local/sbin/alfred -- -i br-$FREEMESH_TLD -b bat0 -m
   # post-up start-stop-daemon -b --start --exec /usr/local/sbin/batadv-vis -- -i bat0 -s

source /etc/network/interfaces.d/*

restart the network, so debian apply the changes in the /etc/network/interfaces:

/etc/init.d/networking restart

give the new IP4 and IPv6 to the bridge:

ip a a [gw ip6 with slash] dev br-$FREEMESH_TLD # for example fdec:c0f1:afda::ff02/64

5. DHCP and DNS

DHCP radvd IPv6

The file /etc/radvd.conf has to be edited.

interface br-$FREEMESH_TLD {
  AdvSendAdvert on;
  # Please uncomment if you don't want an IPv6 default route to be broadcasted.
  # AdvDefaultLifetime 0; 
  IgnoreIfMissing on;
  AdvManagedFlag off;
  AdvOtherConfigFlag on;
  MaxRtrAdvInterval 200;
  prefix $FREEMESH_IP6PREFIX::/64 {
     AdvOnLink on;
     AdvAutonomous on;
     AdvRouterAddr on;
     AdvPreferredLifetime 14400;
     AdvValidLifetime 86400;

  route fc00::/7
     AdvRouteLifetime 1200;

You can restart it now.

service radvd restart

DHCP isc-dhcp-server IPv4 and IPv6

The isc-dhcp-server can not provider IPv4 and IPv6 requests at the same time, so you need to start it in 2 different instances.

The configuration file /etc/dhcp/dhcpd.conf is needed for IPv4 in the freemesh/freifunk network.

ddns-update-style none;
option domain-name ".$FREEMESH_TLD";
option domain-name-servers $FREEMESH_GW_IP4; # make sure to adjust to your gateway fm/ff ipv4
default-lease-time 300;
max-lease-time 3600;
log-facility local7;
  range 10.129.XX.1 10.129.XX.254;    # make sure to adjust to your allocated fm/ff ipv4 range
  option routers 10.129.1.XX;         # make sure to adjust to your gateway fm/ff ipv4

include "/etc/dhcp/static.conf";

Next create an empty static.conf file.

touch /etc/dhcp/static.conf

And create the configuration file /etc/dhcp/dhcpd6.conf for the IPv6 portion.

log-facility local7;

subnet6 $FREEMESH_IPV6_NET {  # for example: fdec:c0f1:afda::/64 
   option $FREEMESH_IPV6;  # make sure to adjust to your gateway fm/ff ipv6
   option dhcp6.domain-search "$FREEMESH_TLD";

Then edit the default start-up files for the ISC dhcpd.

Edit the following sections in /etc/default/isc-dhcp-server

# Additional options to start dhcpd with.
#   Don't use options -cf or -pf here; use DHCPD_CONF/ DHCPD_PID instead
# On what interfaces should the DHCP server (dhcpd) serve DHCP requests?
# Separate multiple interfaces with spaces, e.g. "eth0 eth1".

Create /etc/default/isc-dhcp6-server

nano /etc/default/isc-dhcp6-server

Insert the following sections in /etc/default/isc-dhcp6-server:

# Path to dhcpd's config file (default: /etc/dhcp/dhcpd.conf).

# Path to dhcpd's PID file (default: /var/run/

# Additional options to start dhcpd with.
#   Don't use options -cf or -pf here; use DHCPD_CONF/ DHCPD_PID instead

# On what interfaces should the DHCP server (dhcpd) serve DHCP requests?
#   Separate multiple interfaces with spaces, e.g. "eth0 eth1".

execute the following commands

touch /var/lib/dhcp/dhcpd6.leases
cp /etc/init.d/isc-dhcp-server /etc/init.d/isc-dhcp6-server

edit /etc/init.d/isc-dhcp6-server in 2 places.


# Provides:          isc-dhcp-server


# Provides:          isc-dhcp6-server

and replace




then install the init.d script for the IPv6 DHCPd

update-rc.d isc-dhcp6-server defaults

and you can now restart the dhcpd services

service isc-dhcp-server restart
service isc-dhcp6-server restart


For DNS, my personal preference is on powerdns, but you can use whatever dns you'd like to use. Edit the following sections of the configuration in /etc/powerdns/pdns.conf

# allow-recursion       List of subnets that are allowed to recurse
# local-address Local IP addresses to which we bind
local-address=10.129.1.XX         # add your freemesh/freifunk gateway ipv4 here
# local-ipv6    Local IP address to which we bind
local-ipv6=$FREEMESH_IPV6    # add your freemesh/freifunk gateway ipv6 here
# recursor      If recursion is desired, IP address of a recursing nameserver
recursor=                  # using Google DNS as recursor, as the local one can be buggy

Fetch your Freemesh zones from github. For Example here with the ffcux zones:

cd /etc/powerdns
git clone
ln -s /etc/powerdns/dns_ffcux

Edit /etc/powerdns/bindbackend.conf and add

include "/etc/powerdns/dns_ffcux/named.conf.local";

Now you can restart the dns server

service pdns restart

To keep your dns zone up to date, create the script in your dns directory:

nano /etc/powerdns/dns_ffcux/

Insert this code in your

# hop into correct directory to avoid cron pwd sucks
cd /etc/powerdns/dns_ffcux/
# function to get the current sha-1
getCurrentVersion() {
  git log --format=format:%H -1
# get sha-1 before pull
git pull -q
# get sha-1 after pull
# if sha-1 changed, restart the nameserver
if [ "$revision_current" != "$revision_new" ]
 service pdns restart

Make your executable:

chmod +x

Create an crontab for your

cronetab -e

Insert in your crontab:

*/5 * * * * /etc/powerdns/dns_ffcux/

6. VPN

Depending on where your gateway is located, you may want to set a VPN up to the likes of Mullvad or AirVPN. This example assumes Mullvad, but can be used with any other service.

If you don't need to use a VPN for traffic, then all you need to do is to add the following lines into the eth0 section of /etc/network/interfaces:

  up /sbin/iptables -t nat -A POSTROUTING -s ! -d -j SNAT -o eth0 --to-source $FREEMESH_PUBLIC_IPV4
  up /sbin/ip6tables -t nat -A POSTROUTING -o eth0 -s $FREEMESH_IPV6_NET -j MASQUERADE

This is placed after up /sbin/brctl addbr br-$FREEMESH_TLD

Otherwise .... everything below is what you need to set your VPN tunnel up.

First create /root/bin

mkdir /root/bin

Create the firewall script, needed for the forwarding into the tunnel

nano /root/bin/
/sbin/ip route add default via [your public ip here] table 42
/sbin/ip route add dev br-$FREEMESH_TLD src 10.129.1.XX table 42 # your freemesh/freifunk ip for your gateway here
/sbin/ip route add 0/1 dev tun0 table 42
/sbin/ip route add 128/1 dev tun0 table 42
/sbin/ip route del default via [your public ip here] table 42
/sbin/ip -6 route add $FREEMESH_IPV6_NET dev br-$FREEMESH_TLD table 42
/sbin/ip -6 route add default dev tun0 table 42
/sbin/iptables -t nat -I POSTROUTING -s 0/0 -d 0/0 -j MASQUERADE
/sbin/iptables -t nat -D POSTROUTING -s 0/0 -d 0/0 -o tun0 -j MASQUERADE
/sbin/iptables -t mangle -I PREROUTING -s -j MARK --set-mark 0x1
/sbin/iptables -t mangle -I OUTPUT -s -j MARK --set-mark 0x1
/sbin/ip6tables -t nat -A POSTROUTING -o tun0 -s $FREEMESH_IPV6_NET -j MASQUERADE
/sbin/ip6tables -t mangle -I PREROUTING -s $FREEMESH_IPV6_NET -j MARK --set-mark 0x1
/sbin/ip6tables -t mangle -I OUTPUT -s $FREEMESH_IPV6_NET -j MARK --set-mark 0x1

Then make the firewall script executable.

chmod +x /root/bin/

Then create a script for, that is executed, after the VPN has come up in /root/bin/ and make it executable.

ip route replace via $5 table 42
ip route replace via $5 table 42

service ssh restart
exit 0

You also need to retrieve the mullvad_de.ovpn or mullvad_dk.ovpn (depending on what you want) from Mullvad. You'll find that in Download - iOS, Android and other platforms - Instructions and configuration files. Select your configuration and servers, then get the config. Place the file in /etc/openvpn and rename it to *.conf, as openvpn won't pick it up otherwise.

In the file add the following just above the <ca> section.

# custom
up /root/bin/   
up /root/bin/

And comment the following section out for now:

# Needed to make OpenVPN work on iOS9
# redirect-gateway ipv6

After a reboot everything should be coming online as it's supposed to be and just work away.

HopGlass Server and Web

To view, what's happening on the network you need something like HopGlass or Meshviewer.

HopGlass Web presence

The HopGlass Web presence will need to be installed first, as the hopglass-server installation will re-install another version of npm and hopglass web will not compile with that:

cd /opt
apt-get install apache2
a2enmod proxy
a2enmod proxy_http

Edit the file /etc/apache2/sites-enabled/000-default.conf or whichever is your apache virtualhost for the hopglass map and add the following section before </VirtualHost>:

ProxyPass "/hopglass/" "http://[::1]:4000/"
ProxyPassReverse "/hopglass/" "http://[::1]:4000/"

Then restart apache2

service apache2 restart
cd /opt/hopglass
apt-get install npm

Another thing, that has happened in some cases, is that the nodejs script was not linked to node properly. Check if /usr/bin/node exists after installation and if not:

cd /usr/bin
ln -s nodejs node

Then continue:

npm install
npm install grunt-cli

Follow the hopglass-web manual.

When you're finished, edit the config.json file in the web path. The section, that specificly is important is:

"dataPath": "/hopglass/",

HopGlass Server

HopGlass server can be found at It's installation is described in

An important thing to note though is, that if your setup uses a bridge (like above), your hopglass-server needs to listen on the bridge interface (br-$FREEMESH_TLD) and not the batman interface (bat0).

If systemctl isn't used on your server or the script complains about it, edit /etc/network/interfaces and add the following line after the iface bat0 section:

post-up su - hopglass -s /bin/bash -c 'node --harmony /opt/hopglass/server/hopglass-server.js --config /etc/hopglass-server/config.json' >> /var/log/hopglass-server.log 2>> /var/log/hopglass-server.err &

Then prep the /etc directory for the config etc.

cd /etc
mkdir hopglass-server
chown hopglass.hopglass hopglass-server
cd hopglass-server

Create your /etc/hopglass-server/config.json like this:

  "receiver": {
    "receivers": [
      { "module": "announced",
        "config": {
          "target": {
            "ip": "ff02::1",
            "port": 1001
          "port": 45123,
          "interval": {
            "statistics": 60,
            "nodeinfo": 500
        "overlay": false
      { "module": "aliases",
        "config": {
          "file": "/etc/hopglass-server/aliases.json"
        "overlay": true
    "ifaces": [
    "storage": {
      "file": "/etc/hopglass-server/raw.json"
    "purge": {
      "maxAge": 14
  "provider": {
    "offlineTime": 900
  "webserver": {
    "ip": "::1",
    "port": 4000

You can now start the hopglass-server by running the above command (without the post-up) or rebooting the server.


Grab the following .deb packages directly from Debian sid/unstable or testing (as they're not in stable)

Install the packages using dpkg -i <filename>.

Of course, there will be errors, once you installed the 5, run apt-get -f install and Debian will proceed to install any other packages needed in the dependencies. You can then install the packages again using dpkg -i to make sure they were installed correctly.

After prometheus is installed, add the following section at the bottom of /etc/prometheus/prometheus.yml:

- job_name: 'node_map'
  scrape_interval: 60s
  scrape_timeout: 15s
  metrics_path: '/hopglass/metrics'
    - targets: ['localhost']

- job_name: pushgateway
  honor_labels: true
    - targets: ['localhost:9091']

Make sure, the syntax matches the remainder of the config file. Prometheus is picky. Restart prometheus with service prometheus restart and that's it.

If you have issues with prometheus not starting during boot (happened to me), you can add it under the start of the hopglass-server in /etc/network/interfaces as:

post-up /etc/init.d/prometheus start

It'll start correctly at that point.


Grafana can be downloaded straight from here. They have Debian and Ubuntu packages.

Install the package using dpkg -i <packagename>.

Enable grafana using:

/bin/systemctl daemon-reload
/bin/systemctl enable grafana-server

And then replace /etc/grafana/grafana.ini with the following configuration:

# /etc/grafana/grafana.ini
protocol = http
http_addr =
http_port = 3000
root_url = %(protocol)s://%(domain)s:%(http_port)s/grafana/

enabled = true
org_name = Freifunk Flensburg
org_role = Viewer

# disable user signup / registration
allow_sign_up = false
allow_org_create = false
auto_assign_org = true
auto_assign_org_role = Viewer
login_hint = email or username
default_theme = light

Make sure to set the "org_name" in the auth.anonymous section to the same name as your dashboard, so the graphs can be shown without having to log in.

Edit your apache2 configuration for every virtualhost you want to enable this in, for example /etc/apache2/sites-enabled/000-default.conf:

ProxyPass "/grafana/" "http://localhost:3000/"
ProxyPassReverse "/grafana/" "http://localhost:3000/"

Just before the </Virtualhost> statement.

You can now start the grafana-server:

systemctl start grafana-server

Grab the configuration files from the repository:

Browse to http://yourhost/grafana/ and log in using admin as username and admin as password. Don't forget to change the admin password !!

  • Go to Data Sources, click Add data source
  • specify the name prometheus
  • specify the type prometheus
  • check default checkbox
  • specify the url http://localhost:9090
  • specify access as proxy
  • click Add
  • click Save & Test

You want to edit the file supernodes with the details of your gateways.

Then go to Dashboards -> Import -> Upload .json file and upload one file after the other.

Done .. your graphs should now be working.



vnStat is easy, as there are Debian packages

apt-get install vnstat

After that, all you need to do ist to edit /etc/vstat.conf to adjust the interface, that it collects the statistics on. The default is eth0. If you use an openvpn tunnel, you may have to change this to tun0.


vnStat-php can be downloaded from github. It's found at PHP is also needed.

cd /var/www/html/
git clone vnstat
apt-get install apache2 libapache2-mod-php5

Edit the file config.php and change the language (default nl) to whatever language you want it on and adjust the interfaces as needed.

Get Help

Those Communities already installed a Gateway with this manual: