Benutzer-Werkzeuge


    Warning: Undefined array key "REMOTE_USER" in /usr/local/www/wiki.freifunk-bielefeld.de/lib/tpl/starter/main.php on line 62
  • Admin

  • Warning: Undefined array key "REMOTE_USER" in /usr/local/www/wiki.freifunk-bielefeld.de/lib/tpl/starter/tpl_functions.php on line 50

    Warning: Undefined array key "REMOTE_USER" in /usr/local/www/wiki.freifunk-bielefeld.de/lib/tpl/starter/tpl_functions.php on line 77
  • Registrieren

Webseiten-Werkzeuge


Dies ist eine alte Version des Dokuments!


Aufsetzen eines Gatewayservers mit BATMAN-adv/N2N/OpenVPN

Dieses Howto ist für Leute gedacht die selber einen Server bereitstellen wollen der als N2N Knotenpunkt und Gateway dient. Das heißt das viele Knoten (z.B. Router) sich über diesen Server verbinden können und zudem eine Internetanbindung zur Verfügung gestellt wird. Die Anleitung ist definitiv für fortgeschrittene Nutzer gedacht und wurde für Debiansysteme geschrieben.

Anstatt einer N2N-Supernode kann der Server batürlich auch als edge am Freifunknetz teilnehmen und als Gateway funktionieren. Ebenso kann eine Server einfach nur eine Supernode, ohne Gateway, betreiben.

Installation von N2N

apt-get install subversion
apt-get install libssl-dev
svn co https://ntop.org/svn/ntop/trunk/n2n/n2n_v2/
cd n2n_v2
make && make install

Installation von OpenVPN

apt-get install openvpn

Installation von BATMAN-adv

apt-get install build-essential 
apt-get install linux-headers-$(uname -r)
VERSION=2013.0.0
wget http://downloads.open-mesh.org/batman/releases/batman-adv-$VERSION/batctl-$VERSION.tar.gz
tar -xzf batctl-$VERSION.tar.gz
cd batctl-$VERSION/
make && make install
cd ..
wget http://downloads.open-mesh.org/batman/releases/batman-adv-$VERSION/batman-adv-$VERSION.tar.gz
tar -xzf batman-adv-$VERSION.tar.gz
cd batman-adv-$VERSION/
make && make install

Installation von Nodogsplash

Eine Splashseite ist nicht nötig; kann aber sinnvoll sein um Dauerbenutzer auszubremsen solange kein traffic-shaping verwendet wird. Nodogsplash funktioniert z.Z. nicht als 64bit Programm. Daher müssen wir es als 32bit kompilieren:

apt-get install gcc-multilib

git clone https://github.com/mwarning/nodogsplash.git
cd nodogsplash
CFLAGS="-m32" ./configure --prefix=/usr --sysconfdir=/etc
make
make install

Wenn nodogsplash beim Start libhttpd.so.0 nicht findet muss noch „ldconfig“ ausgeführt werden.

Installation der Statusseite

Eine kleine Statusseite die den Verkehr und den Status des Gateways anzeigt. Dafür wird lighttpd und ein CGI-Script verwendet.

apt-get install lighttpd
apt-get install gawk

gawk wird für das CGI-Script benötigt. Der Inhalt von /etc/lighttpd/lighttpd.conf:

server.document-root = "/etc/lighttpd/www/" 

server.port = 80
server.bind = "10.29.x.y"

server.username = "www" 
server.groupname = "www"
mimetype.assign = (
  ".html" => "text/html", 
  ".txt" => "text/plain",
  ".jpg" => "image/jpeg",
  ".png" => "image/png", 
  ".css" => "text/css"
)

index-file.names = ( "index.html" )

In der Konfigurationsdatei muss anstatt 10.29.x.y die korrekte IP eingetragen werden unter der die Statusseite im Freifunknetz erreichbar sein soll.

Der Inhalt von /etc/lighttpd/generate.sh:

#!/bin/bash

dst="$1"
src="/tmp/index.html.tmp"

#write stdout to file
exec >"$src" 2>&1

convert() {
  echo $1 | awk '{
  split("B,KiB,MiB,GiB,TiB,EiB,PiB,YiB,ZiB", s, ",")
  c=1; x=$1
  while (x>=1024 && c<8) {x/=1024; c++}
  xf=(c==1)?"%d":"%.2f"
  printf(xf" %s\n", x, s[c])
  }'
}

handle() {
  local ifname="$1" tx_id=$2 rx_id=$3
  ifconfig "$ifname" &> /dev/null || return

  get() { cat "/sys/class/net/$ifname/statistics/$1"; }

  tx_bytes=`get tx_bytes`
  rx_bytes=`get rx_bytes`

  avg_time=5
  sleep $avg_time
  tx_speed=$(((`get tx_bytes`-$tx_bytes)/$avg_time))
  rx_speed=$(((`get rx_bytes`-$rx_bytes)/$avg_time))

  #connections=`netstat -nt | awk '{ print $5}' | cut -d: -f1 | sed -e '/^$/d' | sort -n | uniq | wc -l`

  echo '<script type="text/javascript">'
  echo "document.getElementById('$tx_id').innerHTML='`convert $tx_bytes` (`convert $tx_speed`/s)';"
  echo "document.getElementById('$rx_id').innerHTML='`convert $rx_bytes` (`convert $rx_speed`/s)';"
  echo '</script>'
}

echo '<html>'
echo '<head>'
echo '<title>Gateway-Status</title>'
echo '<link rel="stylesheet" type="text/css" href="style.css">'
echo '</head>'
echo '<body>'

echo '<h2>Statusseite des Gateways von Freifunk Bielefeld</h2>'
echo "<center>(`date`)</center>"

echo '<table>'
echo '<tr style="vertical-align:bottom;">'
echo '<td id="left_top"></td>'
echo '<td id="middle_top"></td>'
echo '<td id="right_top"></td>'
echo '</tr>'
echo '<tr>'
echo '<td colspan=3><img src="schema.png" class="schema"></td></tr>'
echo '<tr style="vertical-align:top;">'
echo '<td id="left_bottom"></td>'
echo '<td id="middle_bottom"></td>'
echo '<td id="right_bottom"></td>'
echo '</tr>'
echo '</table>'

handle "tun0" 'left_top' 'left_bottom'
handle "n2n_bat" 'right_bottom' 'right_top'


u=`uptime`
load="${u##*:}"
u="${u%%,*}"
uptime="${u##*up}"
hdd=`df -h | grep '/$' | cut -d' ' -f 20`

echo '<script type="text/javascript">'
echo "document.getElementById('middle_top').innerHTML='<b>Load:</b>$load<br><b>Uptime:</b>$uptime';"
echo "document.getElementById('middle_bottom').innerHTML='<b>HDD:</b> $hdd<br><a href="/vnstat-test/index.php">Traffic Statistics</a>';"
echo '</script>'

echo '</body>'
echo '</html>'

#move to final destiantion
mv "$src" "$dst"

exit 0

Das obige Script generiert die Statusseite und soll alle zwei Minuten ausgeführt werden. Dafür wird ein Eintrag in die /etc/crontab vorgenommen:

*/2 *   * * *   www    /etc/lighttpd/generate.sh '/etc/lighttpd/www/index.html'

Das gewählte Inhaltsverzeichnis muss noch erstellt werden:

mkdir /etc/lighttpd/www

Bevor lighttpd gestartet wird wird dafür noch eine Nutzer und eine Gruppe angelegt:

groupadd www
useradd -g www -d /etc/lighttpd/www -s /sbin/nologin www

chown -R www:www /etc/lighttpd/www/
chmod -R 775 /etc/lighttpd/www/

Nun kann der Webserver gestartet werden.

/etc/init.d/lighttpd start

*vnstat*

apt-get install php5-cgi
apt-get install vnstat
vnstat -u -i n2n_bat
vnstat -u -i tun0

In der /etc/vnstat.conf muss unter #default Interface:

Interface "tun0"
Interface 'n2n_bat"

In /etc/lighttpd/lighttpd.conf muss dann hinzugefügt werden:

server.modules = ("mod_fastcgi")
fastcgi.server = ( ".php" => ((
                   "bin-path" => "/usr/bin/php-cgi",
                   "socket" => "/tmp/php.socket"
               )))

und

index-file.names = ( "index.html" )

wird durch

index-file.names = ( "index.html", "index.php" )

ersetzt

Nun muss nur noch das php-frontend (http://www.sqweek.com/sqweek/files/vnstat_php_frontend-1.5.1.tar.gz) in den richtigen Pfad heruntergeladen und entpackt werden und die config.php angepasst werden: Alle Interfaces müssen als array aufgeführt sein:

    $iface_list = array('tun0', 'n2n_bat', 'eth0');

und für Jedes Interface wird noch ein Titel vergeben

  $iface_title['tun0'] = 'VPN';
  $iface_title['n2n_bat'] = 'Freifunk';
  $iface_title['eth0'] = 'Internet';

Konfiguration von N2N/BATMAN-adv

Da diese Node als Server und Gateway laufen soll muss eine supernode-Instanz und eine edge-Instanz gestartet werden.

Es wird noch tunctl und brctl benötigt:

apt-get install uml-utilities
apt-get install bridge-utils

Dieses Script konfiguriert und startet die Dienste.

#!/bin/bash

exec >/var/log/freifunk_watchdog.log 2>&1
date

n2n_port=60211
mesh_mac=`cat /sys/class/net/eth0/address`

#translate to local administered mac
a=${mesh_mac%%:*} #cut out first hex
a=$((0x$a | 2)) #set second bit to 1
a=`printf '%02x\n' $a` #convert to hex
mesh_mac="$a:${mesh_mac#*:}" #reassemble mac

mac2ip()
{
  #Get the IP of a node by MAC.
  
  mac=$1
  ff_subnet=29
  
  [ -z "$mac" -o -z "$ff_subnet" -o ${#mac} -ne 17 ] && {
    echo "0.0.0.0"
    exit 1
  }
  
  seed=0
  for x in $(echo $mac | tr ":" "\n"); do
    seed=$((seed + 0x$x + (0x$x << 8) + (0x$x << 16)))
  done
  
  addr_t=$((1900545 + (seed % 65278)))
  addr_c=$(((addr_t & 0xff00) >> 8))
  addr_d=$(((addr_t & 0x00ff) >> 0))
  
  echo "10.$ff_subnet.$addr_c.$addr_d"
}

mesh_ip=`mac2ip "$mesh_mac"`
 

is_running() {
  ps aux | grep -v grep | grep "$1" > /dev/null
}

error() {
  echo "(E) $1"
  exit 1
}

if is_running "supernode"; then
  echo "(I) N2N supernode is running."
else
  echo "(I) Start N2N supernode."
  supernode -l "$n2n_port" -v || error "Cannot start N2N supernode."
fi

if is_running "edge"; then
  echo "(I) N2N edge is running."
else
  echo "(I) Start N2N edge."
  edge  -d n2n_bat -a 0.0.0.0 -c ffb1 -l localhost:"$n2n_port" ||  error "Cannot start N2N edge."
fi
 

if batctl o &> /dev/null; then
  echo "(I) batman-adv is running."
else
  echo "(I) Setup batman-adv."

  modprobe batman-adv
  
  echo "(I) Detach all interfaces from batman-adv."
  batctl if del n2n_bat &> /dev/null
  batctl if del dummy_bat &> /dev/null

  echo "(I) Create and attach dummy_bat to control the batman-adv primary interface mac."
  tunctl -t dummy_bat > /dev/null
  ifconfig dummy_bat down #needed?
  ifconfig dummy_bat hw ether "$mesh_mac" mtu 1400 0.0.0.0 up
  batctl if add dummy_bat || error "Failed to attach interface dummy_bat to batman-adv."
  batctl if add n2n_bat || error "Failed to attach interface n2n_bat to batman-adv."
  ifconfig bat0 up

  echo "(I) Configure batmn-adv."
  #for now we don't have internet yet
  echo "client" > /sys/class/net/bat0/mesh/gw_mode
  echo "3000" >  /sys/class/net/bat0/mesh/orig_interval
  echo "1" > /sys/class/net/bat0/mesh/bridge_loop_avoidance 

  echo "(I) Setup br-mesh."
  #We could use just plainbat0 instead of br-mesh
  #But it might give us moreflexibility in the future.
  brctl addbr br-mesh
  brctl addif br-mesh bat0
  echo "(I) Set IP '$mesh_ip' for br-mesh."
  ifconfig br-mesh "$mesh_ip" up
fi

is_running "openvpn " || /etc/init.d/openvpn start

vpn_interface="tun0"
ping_servers()
{
  echo "(I) Try to ping root servers on '$vpn_interface':"
  
  #shuffle list and pick n entries
  pick()
  {
    local n=$1; shift;
    local s="`echo \"$@\" | tr ' ' '\n' | awk 'BEGIN { srand() } { print rand() "\t" $0 }' | sort -n | cut -f2- | tr '\n' ' '`"
    get() { shift $(($#-$1)); echo "$@"; }
    get $n $s
  }
  
  #check if any root server can be reached via default gateway and wan interface
  IPCHECK="192.33.4.12 128.8.10.90 193.0.14.129 198.41.0.4 192.228.79.201 192.5.5.241 192.36.148.17 192.58.128.30"
  for ip in `pick 3 $IPCHECK`; do
    echo -n "(I) Ping '$ip' "
    if ping $ip -c 1 -I $vpn_interface -q -W 1 > /dev/null 2>&1; then
      echo "- success."
      return 0
    else
      echo "- failed."
    fi
  done
  echo "(W) Cannot reach any tested IP."
  return 1
}

if ifconfig "$vpn_interface" &> /dev/null && ping_servers; then
  echo "(I) Internet access on '$vpn_interface' => Server mode."
  batctl gw_mode server
else
  echo "(I) No Internet access on '$vpn_interface'. => Client mode."
  batctl gw_mode client
fi

echo "(I) Done."

Dieses Script kann einmal nach dem Systemstart oder regelmäßig durch cron aufgerufen werden. Dafür muss folgende Zeile an die /etc/crontab angehängt werden:

*/5 *   * * *   root    /root/freifunk_watchdog > /dev/null

Wichig ist dabei, dass das Script ausführbar ist:

chmod a+x freifunk_watchdog

Konfiguration von nodogsplash

Für die Konfigurationsdatei /etc/nodogsplash/nodogsplash.conf wird eine verwendet die nahezu identisch mit der auf den Routern ist:

#
# Nodogsplash Configuration File
#
# For the config file documentation along with examples look at
# the default configuration file of the nodogsplash package:
# https://github.com/mwarning/nodogsplash/blob/master/nodogsplash.conf
#
# For the general documentation look here:
# http://kokoro.ucsd.edu/nodogsplash/

GatewayInterface bat0 

FirewallRuleSet preauthenticated-users {
    FirewallRule allow tcp port 53
    FirewallRule allow udp port 53
}

EmptyRuleSetPolicy authenticated-users passthrough
EmptyRuleSetPolicy users-to-router passthrough
EmptyRuleSetPolicy trusted-users allow
EmptyRuleSetPolicy trusted-users-to-router passthrough

MaxClients 80
ClientIdleTimeout 10
ClientForceTimeout 240

Der Inhalt von /etc/nodogsplash/htdocs/ mit der eigentlichen Splash-Seite ist identisch mit der auf dem Router.

Konfiguration von OpenVPN

Zuerst sorgen wir dafür das OpenVPN beim Booten nicht automatisch startet:

update-rc.d -f openvpn remove

Die Konfiguration für OpenVPN kommt vom VPN-Anbieter in Form einer komprimierten Datei die nach /etc/openvpn entpackt wird:

unzip 1234.zip
cp -f 1234/* /etc/openvpn/
rm -rf 1234

In der Konfigurationsdatei /etc/openvpn/1234.conf müssen die beiden Zeilen die mit „up“ und „down“ beginnen auskommentiert werden. Zusätzlich werden Einstellungen hinzugefügt:

echo "route-noexec" >> /etc/openvpn/1234.conf
echo "route-up /etc/openvpn/update-route" >> /etc/openvpn/1234.conf

Damit wird OpenVPN so eingestellt das die routing-Tabelle main (ip route show table main) nicht verändert wird und stattdessen ein Script (update-route) aufgerufen wird das die Einträge vom DHCP Server in einen eigene Tabelle „vpn“ einträgt.

Das Script /etc/openvpn/update-route:

#!/bin/bash
#Script called by OpenVPN with network/gateway information.

vpn_interface="$dev"
vpn_gateway="$route_gateway_1"
mesh_interface="br-mesh"

exec >/var/log/update-route.log 2>&1
date

echo "(I) vpn_interface: '$vpn_interface'"
echo "(I) vpn_gateway: '$vpn_gateway'"
echo "(I) mesh_interface: '$mesh_interface'"

#setup table if it does not exist yet
ip route show table vpn &> /dev/null || echo 100 vpn >> /etc/iproute2/rt_tables

#cleanup previous table
ip rule del table vpn &> /dev/null
while ip route del default table vpn &> /dev/null; do true; done

#set new gateway in openvon network
ip route add default via "$vpn_gateway" dev "$vpn_interface" table vpn
ip rule add dev "$mesh_interface" table vpn
ip route flush cache

#enable packet forwarding to function s a router
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables --append FORWARD --in-interface "$mesh_interface" -j ACCEPT
#Enable MASQUERADE to function as a NAT router
iptables --table nat --append POSTROUTING --out-interface "$vpn_interface" -j MASQUERADE

Die Datei muss noch ausführbar gemacht werden:

chmod a+x /etc/openvpn/update-route

Zugriff auf dem Server per ssh aus dem Freifunknetz (über bat0) ist weiterhin möglich. Um den Zugriff zu verhindern bitte „iptables -A INPUT -p tcp -i bat0 –dport 22 -j DROP“ einfügen.

VPN-Test / Durchsatz vom VServer über den VPN-Endpunkt

abends

root@ffbi-gw1:~# iperf -c <****>
------------------------------------------------------------
Client connecting to <****>, TCP port 5001
TCP window size: 16.0 KByte (default)
------------------------------------------------------------
[  3] local 10.8.0.190 port 42312 connected with <****> port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0-10.1 sec  12.6 MBytes  10.5 Mbits/sec
root@ffbi-gw1:~# iperf -c <****>
------------------------------------------------------------
Client connecting to <****>, TCP port 5001
TCP window size: 16.0 KByte (default)
------------------------------------------------------------
[  3] local 10.8.0.190 port 42313 connected with <****> port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0-10.0 sec  19.2 MBytes  16.0 Mbits/sec

morgens, 10:15

root@ffbi-gw1:~# iperf -c <****>
------------------------------------------------------------
Client connecting to <****>, TCP port 5001
TCP window size: 16.0 KByte (default)
------------------------------------------------------------
[  3] local 10.8.0.190 port 42314 connected with <****> port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0-10.0 sec  18.5 MBytes  15.5 Mbits/sec
root@ffbi-gw1:~# iperf -c <****>
------------------------------------------------------------
Client connecting to <****>, TCP port 5001
TCP window size: 16.0 KByte (default)
------------------------------------------------------------
[  3] local 10.8.0.190 port 42315 connected with <****> port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0-10.1 sec  20.8 MBytes  17.3 Mbits/sec
root@ffbi-gw1:~# iperf -c <****>
------------------------------------------------------------
Client connecting to <****>, TCP port 5001
TCP window size: 16.0 KByte (default)
------------------------------------------------------------
[  3] local 10.8.0.190 port 42316 connected with <****> port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0-10.1 sec  23.8 MBytes  19.9 Mbits/sec
root@ffbi-gw1:~# iperf -c <****>
------------------------------------------------------------
Client connecting to <****>, TCP port 5001
TCP window size: 16.0 KByte (default)
------------------------------------------------------------
[  3] local 10.8.0.190 port 42317 connected with <****> port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0-10.0 sec  16.4 MBytes  13.7 Mbits/sec