diff --git a/Makefile b/Makefile index 42381cc9..65901baf 100644 --- a/Makefile +++ b/Makefile @@ -28,6 +28,7 @@ install: cp img/avatars/* ${DESTDIR}/usr/share/${APP}/avatars cp src/* ${DESTDIR}${PREFIX}/bin cp src/${APP}-mesh-batman ${DESTDIR}${PREFIX}/bin/batman + cp src/${APP}-mesh-bmx6 ${DESTDIR}${PREFIX}/bin/bmx cp src/${APP}-backup-local ${DESTDIR}${PREFIX}/bin/backup cp src/${APP}-backup-local ${DESTDIR}${PREFIX}/bin/backup2friends cp src/${APP}-restore-local ${DESTDIR}${PREFIX}/bin/restore @@ -60,6 +61,7 @@ uninstall: rm -f ${PREFIX}/bin/restore rm -f ${PREFIX}/bin/restorefromfriend rm -f ${PREFIX}/bin/batman + rm -f ${PREFIX}/bin/bmx rm -rf /etc/${APP} rm -f ${PREFIX}/bin/control rm -f ${PREFIX}/bin/controluser diff --git a/src/freedombone-image-customise b/src/freedombone-image-customise index 5ba0f7a0..c4d69045 100755 --- a/src/freedombone-image-customise +++ b/src/freedombone-image-customise @@ -13,6 +13,8 @@ # License # ======= # +# Copyright (C) 2015-2018 Bob Mottram <bob@freedombone.net> +# # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -123,6 +125,9 @@ ENABLE_ZERONET= MESH_TEXT_EDITOR='pluma' +BMX6_REPO="https://github.com/bashrc/bmx6" +BMX6_COMMIT='20db4cf5abc129b8d4d2a341bb9265a92e7c3d50' + PATH=/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin function configure_backports { @@ -653,6 +658,63 @@ mesh_shutdown_script() { chroot "$rootdir" systemctl enable meshshutdown } +install_bmx6() { + git clone $BMX6_REPO $rootdir/etc/bmx6 + + cat <<EOF > $rootdir/usr/bin/install_bmx6 +#!/bin/bash +cd /etc/bmx6 +git checkout $BMX6_COMMIT -b $BMX6_COMMIT +make +make install + +cd /etc/bmx6/lib/bmx6_http_info +make +make install + +cd /etc/bmx6/lib/bmx6_json +make +make install + +cd /etc/bmx6/lib/bmx6_quagga +make +make install + +cd /etc/bmx6/lib/bmx6_sms +make +make install + +cd /etc/bmx6/lib/bmx6_table +make +make install + +cd /etc/bmx6/lib/bmx6_topology +make +make install +EOF + chroot "$rootdir" chmod +x /usr/bin/install_bmx6 + chroot "$rootdir" /usr/bin/install_bmx6 + + if [ ! -f $rootdir/usr/sbin/bmx6 ]; then + echo $'bmx6 was not installed' + exit 79835292 + fi + + echo '[Unit]' > $rootdir/etc/systemd/system/bmx6.service + echo 'Description=BMX6 mesh routing protocol' >> $rootdir/etc/systemd/system/bmx6.service + echo 'Requires=network.target' >> $rootdir/etc/systemd/system/bmx6.service + echo 'After=network.target' >> $rootdir/etc/systemd/system/bmx6.service + echo '' >> $rootdir/etc/systemd/system/bmx6.service + echo '[Service]' >> $rootdir/etc/systemd/system/bmx6.service + echo 'User=root' >> $rootdir/etc/systemd/system/bmx6.service + echo 'Group=root' >> $rootdir/etc/systemd/system/bmx6.service + echo 'ExecStart=/usr/sbin/bmx6 dev=wlan0' >> $rootdir/etc/systemd/system/bmx6.service + echo 'Restart=on-failure' >> $rootdir/etc/systemd/system/bmx6.service + echo '' >> $rootdir/etc/systemd/system/bmx6.service + echo '[Install]' >> $rootdir/etc/systemd/system/bmx6.service + echo 'WantedBy=multi-user.target' >> $rootdir/etc/systemd/system/bmx6.service +} + initialise_mesh() { if [[ $VARIANT != "mesh"* ]]; then return @@ -692,6 +754,7 @@ initialise_mesh() { configure_firewall install_avahi install_batman + install_bmx6 mesh_shutdown_script install_vpn install_tomb diff --git a/src/freedombone-image-mesh b/src/freedombone-image-mesh index a91722e5..d041a71b 100755 --- a/src/freedombone-image-mesh +++ b/src/freedombone-image-mesh @@ -1415,6 +1415,10 @@ if [ -f $MESH_INSTALL_SETUP ]; then systemctl disable tor echo $'TOR disabled' >> $INSTALL_LOG + systemctl stop bmx6 + systemctl disable bmx6 + echo $'BMX6 disabled' >> $INSTALL_LOG + #tomb slam all tmp_ram_disk 100 enable_predictable_device_names diff --git a/src/freedombone-mesh-batman b/src/freedombone-mesh-batman index a1268b37..7a01f57b 100755 --- a/src/freedombone-mesh-batman +++ b/src/freedombone-mesh-batman @@ -35,57 +35,7 @@ COMPLETION_FILE=/root/${PROJECT_NAME}-completed.txt HOTSPOT_PASSPHRASE="${PROJECT_NAME}" source /usr/share/${PROJECT_NAME}/utils/${PROJECT_NAME}-utils-wifi - -if [[ $1 == "start" ]]; then - # install avahi - sed -i "s|#host-name=.*|host-name=$(hostname)|g" /etc/avahi/avahi-daemon.conf - sed -i "s|host-name=.*|host-name=$(hostname)|g" /etc/avahi/avahi-daemon.conf - sed -i "s|use-ipv4=.*|use-ipv4=yes|g" /etc/avahi/avahi-daemon.conf - sed -i "s|use-ipv6=.*|use-ipv6=no|g" /etc/avahi/avahi-daemon.conf - sed -i "s|#disallow-other-stacks=.*|disallow-other-stacks=yes|g" /etc/avahi/avahi-daemon.conf - sed -i "s|hosts:.*|hosts: files mdns4_minimal dns mdns4 mdns|g" /etc/nsswitch.conf -fi - -# Mesh definition -WIFI_SSID='mesh' -if [ -f $COMPLETION_FILE ]; then - if grep -q "WIFI_SSID:" $COMPLETION_FILE; then - WIFI_SSID=$(cat $COMPLETION_FILE | grep "WIFI_SSID:" | awk -F ':' '{print $2}') - fi - sed -i "s|WIFI_SSID:.*|WIFI_SSID:${WIFI_SSID}|g" $COMPLETION_FILE -fi -CELLID='any' - -CHANNEL=2 -HOTSPOT_CHANNEL=6 -if [ -f $COMPLETION_FILE ]; then - if grep -q "Wifi channel:" $COMPLETION_FILE; then - CHANNEL=$(cat $COMPLETION_FILE | grep "Wifi channel:" | awk -F ':' '{print $2}') - fi - sed -i "s|Wifi channel:.*|Wifi channel:${CHANNEL}|g" $COMPLETION_FILE -fi - -ZERONET_PORT=15441 -IPFS_PORT=4001 -TOX_PORT=33445 -TRACKER_PORT=6969 -LIBREVAULT_PORT=42345 -TAHOELAFS_PORT=50213 -GIT_SSB_PORT=7718 -NGINX_GIT_SSB_PORT=7719 - -# Ethernet bridge definition (bridged to bat0) -BRIDGE=br-mesh -BRIDGE_HOTSPOT=br-hotspot -IFACE= -IFACE_SECONDARY= -EIFACE=eth0 -WLAN_ADAPTORS=$(count_wlan) - -if [ $WLAN_ADAPTORS -eq 0 ]; then - echo $'No wlan adaptors found' - exit 0 -fi +source /usr/share/${PROJECT_NAME}/utils/${PROJECT_NAME}-utils-mesh update_wifi_adaptors @@ -98,23 +48,6 @@ if [ -e /etc/default/batctl ]; then . /etc/default/batctl fi -function get_ipv4_wlan { - echo $(ip -o -f inet addr show dev "$IFACE" | awk '{print $4}' | awk 'END {print}' | awk -F '/' '{print $1}') -} - -function mesh_hotspot_ip_address { - echo $(ip -o -f inet addr show dev "${BRIDGE}" | awk '{print $4}' | awk 'END {print}' | awk -F '/' '{print $1}') -} - -function global_rate_limit { - if ! grep -q "tcp_challenge_ack_limit" /etc/sysctl.conf; then - echo 'net.ipv4.tcp_challenge_ack_limit = 999999999' >> /etc/sysctl.conf - else - sed -i 's|net.ipv4.tcp_challenge_ack_limit.*|net.ipv4.tcp_challenge_ack_limit = 999999999|g' /etc/sysctl.conf - fi - sysctl -p -q -} - function status { batctl o } @@ -160,44 +93,7 @@ function stop { rmmod batman-adv - iptables -D INPUT -p tcp --dport $TRACKER_PORT -j ACCEPT - iptables -D INPUT -p udp --dport $TRACKER_PORT -j ACCEPT - iptables -D INPUT -p tcp --dport 80 -j ACCEPT - iptables -D INPUT -p udp --dport 80 -j ACCEPT - iptables -D INPUT -p tcp --dport 548 -j ACCEPT - iptables -D INPUT -p udp --dport 548 -j ACCEPT - iptables -D INPUT -p tcp --dport 5353 -j ACCEPT - iptables -D INPUT -p udp --dport 5353 -j ACCEPT - iptables -D INPUT -p tcp --dport 5354 -j ACCEPT - iptables -D INPUT -p udp --dport 5354 -j ACCEPT - iptables -D INPUT -p tcp --dport $ZERONET_PORT -j ACCEPT - iptables -D INPUT -p udp --dport $ZERONET_PORT -j ACCEPT - iptables -D INPUT -p tcp --dport $IPFS_PORT -j ACCEPT - iptables -D INPUT -p udp --dport $IPFS_PORT -j ACCEPT - iptables -D INPUT -p tcp --dport $TOX_PORT -j ACCEPT - iptables -D INPUT -p udp --dport $TOX_PORT -j ACCEPT - iptables -D INPUT -p tcp --dport $LIBREVAULT_PORT -j ACCEPT - iptables -D INPUT -p udp --dport $LIBREVAULT_PORT -j ACCEPT - iptables -D INPUT -p tcp --dport $TAHOELAFS_PORT -j ACCEPT - # SSB/Scuttlebot/Patchwork - iptables -D INPUT -p tcp --dport $GIT_SSB_PORT -j ACCEPT - iptables -D INPUT -p udp --dport 8008 -j ACCEPT - iptables -D INPUT -p tcp --dport 8008 -j ACCEPT - iptables -D INPUT -p udp --dport 8010 -j ACCEPT - iptables -D INPUT -p tcp --dport 8010 -j ACCEPT - # vpn over the internet - iptables -D INPUT -p tcp --dport 653 -j ACCEPT - iptables -D INPUT -p udp --dport 653 -j ACCEPT - iptables -D INPUT -i ${EIFACE} -m state --state NEW -p tcp --dport 1194 -j ACCEPT - iptables -D INPUT -i tun+ -j ACCEPT - iptables -D FORWARD -i tun+ -j ACCEPT - iptables -D FORWARD -i tun+ -o ${EIFACE} -m state --state RELATED,ESTABLISHED -j ACCEPT - iptables -D FORWARD -i ${EIFACE} -o tun+ -m state --state RELATED,ESTABLISHED -j ACCEPT - iptables -t nat -D POSTROUTING -s 10.8.0.0/24 -o ${EIFACE} -j MASQUERADE - iptables -D OUTPUT -o tun+ -j ACCEPT - - echo 0 > /proc/sys/net/ipv4/ip_forward - sed -i 's|net.ipv4.ip_forward=.*|net.ipv4.ip_forward=0|g' /etc/sysctl.conf + disable_mesh_firewall systemctl restart network-manager } @@ -215,21 +111,6 @@ function verify { rm $tempfile } -function assign_peer_address { - for i in {1..6}; do - number=$RANDOM - let "number %= 255" - octet=$(echo "obase=16;$number" | bc) - if [ ${#octet} -lt 2 ]; then - octet="0${octet}" - fi - if [ $i -gt 1 ]; then - echo -n ":" - fi - echo -n "${octet}" - done -} - function add_wifi_interface { ifname=$1 ifssid=$WIFI_SSID @@ -261,53 +142,6 @@ function add_wifi_interface { ifconfig $ifname up } -function mesh_create_app_downloads_page { - if [ ! -d /root/$PROJECT_NAME/image_build/mesh_apps ]; then - return - fi - if [ ! -d /var/www/html ]; then - return - fi - # Don't go straight to cryptpad when navigating to the peer's IP address - if [ -L /etc/nginx/sites-enabled/cryptpad ]; then - rm /etc/nginx/sites-enabled/cryptpad - ln -s /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default - if [ -d /etc/cryptpad ]; then - systemctl stop cryptpad - systemctl disable cryptpad - fi - systemctl restart nginx - fi - # Don't show the cryptpad icon on the desktop - if [ -f /home/fbone/Desktop/cryptpad.desktop ]; then - mv /home/fbone/Desktop/cryptpad.desktop /home/fbone/.cryptpad.desktop - fi - - cp /root/$PROJECT_NAME/website/EN/meshindex.html /var/www/html/index.html - if [ ! -f /var/www/html/ssb.apk ]; then - cp /root/$PROJECT_NAME/image_build/mesh_apps/ssb.apk /var/www/html/ssb.apk - fi - if [ ! -f /var/www/html/trifa.apk ]; then - cp /root/$PROJECT_NAME/image_build/mesh_apps/trifa.apk /var/www/html/trifa.apk - fi - if [ ! -d /var/www/html/images ]; then - mkdir /var/www/html/images - fi - if [ ! -f /var/www/html/images/logo.png ]; then - cp /root/$PROJECT_NAME/img/logo.png /var/www/html/images/logo.png - fi - if [ ! -f /var/www/html/images/ssb.png ]; then - cp /root/$PROJECT_NAME/img/icon_patchwork.png /var/www/html/images/ssb.png - fi - if [ ! -f /var/www/html/images/trifa.png ]; then - cp /root/$PROJECT_NAME/img/trifa.png /var/www/html/images/trifa.png - fi - if [ ! -f /var/www/html/freedombone.css ]; then - cp /root/$PROJECT_NAME/website/freedombone.css /var/www/html/freedombone.css - fi - chown -R www-data:www-data /var/www/html/* -} - function start { update_wifi_adaptors @@ -320,6 +154,8 @@ function start { systemctl stop network-manager sleep 5 + systemctl stop bmx6 + systemctl disable bmx6 systemctl stop dnsmasq systemctl disable dnsmasq @@ -374,142 +210,17 @@ function start { ifconfig $BRIDGE up dhclient $BRIDGE - if [ $secondary_wifi_available ]; then - sed -i 's|#DAEMON_CONF=.*|DAEMON_CONF="/etc/hostapd/hostapd.conf"|g' /etc/default/hostapd + enable_mesh_seconary_wifi - mesh_hotspot_address=$(mesh_hotspot_ip_address) - if [[ "$mesh_hotspot_address" == *'.'* ]]; then - echo "interface=${IFACE_SECONDARY}" > /etc/hostapd/hostapd.conf - echo "bridge=${BRIDGE}" >> /etc/hostapd/hostapd.conf - echo 'driver=nl80211' >> /etc/hostapd/hostapd.conf - echo "country_code=UK" >> /etc/hostapd/hostapd.conf - echo "ssid=${WIFI_SSID}-${mesh_hotspot_address}" >> /etc/hostapd/hostapd.conf - echo 'hw_mode=g' >> /etc/hostapd/hostapd.conf - echo "channel=${HOTSPOT_CHANNEL}" >> /etc/hostapd/hostapd.conf - echo 'wpa=2' >> /etc/hostapd/hostapd.conf - echo "wpa_passphrase=$HOTSPOT_PASSPHRASE" >> /etc/hostapd/hostapd.conf - echo 'wpa_key_mgmt=WPA-PSK' >> /etc/hostapd/hostapd.conf - echo 'wpa_pairwise=TKIP' >> /etc/hostapd/hostapd.conf - echo 'rsn_pairwise=CCMP' >> /etc/hostapd/hostapd.conf - echo 'auth_algs=1' >> /etc/hostapd/hostapd.conf - echo 'macaddr_acl=0' >> /etc/hostapd/hostapd.conf - - sed -i "s|#interface=.*|interface=${IFACE_SECONDARY}|g" /etc/dnsmasq.conf - sed -i "s|interface=.*|interface=${IFACE_SECONDARY}|g" /etc/dnsmasq.conf - sed -i "s|listen-address=.*|listen-address=127.0.0.1,$mesh_hotspot_address|g" /etc/dnsmasq.conf - sed -i 's|#listen-address|listen-address|g' /etc/dnsmasq.conf - systemctl enable dnsmasq - systemctl restart dnsmasq - - systemctl enable hostapd - systemctl restart hostapd - mesh_create_app_downloads_page - else - secondary_wifi_available= - echo $'WARNING: No IP address could be obtained for the hotspot' - fi - fi - - if [ ! $secondary_wifi_available ]; then - systemctl stop hostapd - systemctl disable hostapd - - # Recreate the cryptpad symlink - if [ -f /etc/nginx/sites-available/cryptpad ]; then - if [ -L /etc/nginx/sites-enabled/cryptpad ]; then - rm /etc/nginx/sites-enabled/default - fi - systemctl enable cryptpad - systemctl start cryptpad - - if [ ! -L /etc/nginx/sites-enabled/cryptpad ]; then - ln -s /etc/nginx/sites-available/cryptpad /etc/nginx/sites-enabled/cryptpad - systemctl restart nginx - fi - fi - if [ -f /home/fbone/.cryptpad.desktop ]; then - mv /home/fbone/.cryptpad.desktop /home/fbone/Desktop/cryptpad.desktop - fi - fi - - iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT - iptables -A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT - iptables -A INPUT -p tcp --dport $TRACKER_PORT -j ACCEPT - iptables -A INPUT -p udp --dport $TRACKER_PORT -j ACCEPT - iptables -A INPUT -p tcp --dport 80 -j ACCEPT - iptables -A INPUT -p udp --dport 80 -j ACCEPT - iptables -A INPUT -p tcp --dport 548 -j ACCEPT - iptables -A INPUT -p udp --dport 548 -j ACCEPT - iptables -A INPUT -p tcp --dport 5353 -j ACCEPT - iptables -A INPUT -p udp --dport 5353 -j ACCEPT - iptables -A INPUT -p tcp --dport 5354 -j ACCEPT - iptables -A INPUT -p udp --dport 5354 -j ACCEPT - iptables -A INPUT -p tcp --dport $ZERONET_PORT -j ACCEPT - iptables -A INPUT -p udp --dport $ZERONET_PORT -j ACCEPT - iptables -A INPUT -p tcp --dport $IPFS_PORT -j ACCEPT - iptables -A INPUT -p tcp --dport $TOX_PORT -j ACCEPT - iptables -A INPUT -p udp --dport $TOX_PORT -j ACCEPT - iptables -A INPUT -p tcp --dport $LIBREVAULT_PORT -j ACCEPT - iptables -A INPUT -p udp --dport $LIBREVAULT_PORT -j ACCEPT - iptables -A INPUT -p tcp --dport $TAHOELAFS_PORT -j ACCEPT - # SSB/Scuttlebot/Patchwork - iptables -A INPUT -p tcp --dport $GIT_SSB_PORT -j ACCEPT - iptables -A INPUT -p udp --dport 8008 -j ACCEPT - iptables -A INPUT -p tcp --dport 8008 -j ACCEPT - iptables -A INPUT -p udp --dport 8010 -j ACCEPT - iptables -A INPUT -p tcp --dport 8010 -j ACCEPT - # vpn over the internet - # Note: the vpn firewall settings are needed in order for Patchwork - # to discover local peers - iptables -A INPUT -p tcp --dport 653 -j ACCEPT - iptables -A INPUT -p udp --dport 653 -j ACCEPT - iptables -A INPUT -i ${EIFACE} -m state --state NEW -p tcp --dport 1194 -j ACCEPT - iptables -A INPUT -i tun+ -j ACCEPT - iptables -A FORWARD -i tun+ -j ACCEPT - iptables -A FORWARD -i tun+ -o ${EIFACE} -m state --state RELATED,ESTABLISHED -j ACCEPT - iptables -A FORWARD -i ${EIFACE} -o tun+ -m state --state RELATED,ESTABLISHED -j ACCEPT - iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o ${EIFACE} -j MASQUERADE - iptables -A OUTPUT -o tun+ -j ACCEPT - echo 1 > /proc/sys/net/ipv4/ip_forward - sed -i 's|# net.ipv4.ip_forward|net.ipv4.ip_forward|g' /etc/sysctl.conf - sed -i 's|#net.ipv4.ip_forward|net.ipv4.ip_forward|g' /etc/sysctl.conf - sed -i 's|net.ipv4.ip_forward.*|net.ipv4.ip_forward=1|g' /etc/sysctl.conf + enable_mesh_firewall systemctl restart avahi-daemon - if [ -f /etc/scuttlebot/.ssb/config ]; then - ethernet_connected=$(cat /sys/class/net/eth0/carrier) - if [[ "$ethernet_connected" != "0" ]]; then - sed -i "s|\"host\": .*|\"host\": \"$(get_ipv4_wlan)\",|g" /etc/scuttlebot/.ssb/config - systemctl restart scuttlebot - else - if [ ! -f /etc/nginx/sites-available/git_ssb ]; then - systemctl stop scuttlebot - else - systemctl restart scuttlebot - fi - fi - fi + enable_mesh_scuttlebot + enable_mesh_tor - # if we have an ethernet connection to an internet router then create - # an onion address for this peer - if [[ "$ethernet_connected" != "0" ]]; then - systemctl enable tor - systemctl start tor - HIDDEN_SERVICE_PATH=/var/lib/tor/hidden_service_ - if [ ! -f ${HIDDEN_SERVICE_PATH}mesh/hostname ]; then - echo "HiddenServiceDir ${HIDDEN_SERVICE_PATH}mesh/" >> /etc/tor/torrc - echo "HiddenServicePort 653 127.0.0.1:653" >> /etc/tor/torrc - systemctl restart tor - fi - else - systemctl stop tor - systemctl disable tor - fi - - sed -i "s|\"host\":.*|\"host\": \"${HOSTNAME}.local\",|g" /etc/scuttlebot/.ssb/config sed -i "s|server_name .*|server_name ${HOSTNAME}.local;|g" /etc/nginx/sites-available/git_ssb - systemctl restart scuttlebot + systemctl restart nginx verify diff --git a/src/freedombone-mesh-bmx6 b/src/freedombone-mesh-bmx6 new file mode 100755 index 00000000..2a4a1793 --- /dev/null +++ b/src/freedombone-mesh-bmx6 @@ -0,0 +1,301 @@ +#!/bin/bash +# +# .---. . . +# | | | +# |--- .--. .-. .-. .-.| .-. .--.--. |.-. .-. .--. .-. +# | | (.-' (.-' ( | ( )| | | | )( )| | (.-' +# ' ' --' --' -' - -' ' ' -' -' -' ' - --' +# +# Freedom in the Cloud +# +# Used to enable or disable BMX6 mesh protocol on wlanX +# +# License +# ======= +# +# Copyright (C) 2018 Bob Mottram <bob@freedombone.net> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +PROJECT_NAME='freedombone' +COMPLETION_FILE=/root/${PROJECT_NAME}-completed.txt + +# hotspot passphrase must be 5 characters or longer +HOTSPOT_PASSPHRASE="${PROJECT_NAME}" + +source /usr/share/${PROJECT_NAME}/utils/${PROJECT_NAME}-utils-wifi +source /usr/share/${PROJECT_NAME}/utils/${PROJECT_NAME}-utils-mesh + +update_wifi_adaptors + +if [ ! $IFACE ]; then + echo $'No wlan adaptor' + exit 0 +fi + +function status { + bmx6 -c status +} + +function stop { + if [ -z "$IFACE" ]; then + echo 'error: unable to find wifi interface, not enabling BMX6 mesh' + return + fi + + systemctl stop dnsmasq + systemctl disable dnsmasq + systemctl stop bmx6 + systemctl disable bmx6 + + if [ "$EIFACE" ]; then + ethernet_connected=$(cat /sys/class/net/$EIFACE/carrier) + if [[ "$ethernet_connected" != "0" ]]; then + systemctl stop hostapd + ifconfig $EIFACE down -promisc + fi + fi + + avahi-autoipd -k $BRIDGE + avahi-autoipd -k $IFACE + ifconfig $IFACE down -promisc + + ifconfig $IFACE mtu 1500 + ifconfig $IFACE down + iwconfig $IFACE mode managed + + if [ $IFACE_SECONDARY ]; then + systemctl stop hostapd + systemctl disable hostapd + ifconfig $IFACE_SECONDARY mtu 1500 + ifconfig $IFACE_SECONDARY down + iwconfig $IFACE_SECONDARY mode managed + fi + + disable_mesh_firewall + + systemctl restart network-manager +} + +function verify { + # TODO +} + +function add_wifi_interface { + ifname=$1 + ifssid=$WIFI_SSID + if [ $2 ]; then + ifssid=$2 + fi + ifmode=ad-hoc + if [ $3 ]; then + ifmode=$3 + fi + ifchannel=$CHANNEL + if [ $4 ]; then + ifchannel=$4 + fi + + ifconfig $ifname down + ifconfig $ifname mtu 1500 + peermac=$(assign_peer_address) + if [ ! $peermac ]; then + echo $"Unable to obtain MAC address for $peermac on $ifname" + return + fi + ifconfig $ifname hw ether $peermac + echo $"$ifname assigned MAC address $peermac" + iwconfig $ifname enc off + iwconfig $ifname mode $ifmode essid $ifssid channel $ifchannel + + ifconfig $ifname up +} + +function start { + update_wifi_adaptors + + if [ -z "$IFACE" ] ; then + echo 'error: unable to find wifi interface, not enabling BMX6 mesh' + exit 723657 + fi + echo "info: enabling BMX6 mesh network $WIFI_SSID on $IFACE" + + batman stop + systemctl stop network-manager + sleep 5 + + systemctl stop dnsmasq + systemctl disable dnsmasq + + # remove an avahi service which isn't used + if [ -f /etc/avahi/services/udisks.service ]; then + sudo rm /etc/avahi/services/udisks.service + fi + + global_rate_limit + + # Might have to re-enable wifi + rfkill unblock $(rfkill list|awk -F: "/phy/ {print $1}") || true + + secondary_wifi_available= + if [ $IFACE_SECONDARY ]; then + if [[ $IFACE != $IFACE_SECONDARY ]]; then + if [ -d /etc/hostapd ]; then + if [ ${#HOTSPOT_PASSPHRASE} -gt 4 ]; then + secondary_wifi_available=1 + else + echo $'Hotspot passphrase is too short' + fi + fi + fi + fi + + add_wifi_interface $IFACE $WIFI_SSID ad-hoc $CHANNEL + ifconfig $IFACE up promisc + + if [ ! $secondary_wifi_available ]; then + sed -i "s|ExecStart=.*|ExecStart=/usr/sbin/bmx6 dev=${IFACE}|g" /etc/systemd/system/bmx6.service + else + sed -i "s|ExecStart=.*|ExecStart=/usr/sbin/bmx6 dev=${IFACE} dev=${EIFACE}|g" /etc/systemd/system/bmx6.service + fi + + systemctl daemon-reload + systemctl enable bmx6 + systemctl start bmx6 + + avahi-autoipd --force-bind --daemonize --wait $IFACE + + # NOTE: Don't connect the secondary wifi device. hostapd will handle that by itself + + ethernet_connected='0' + if [ "$EIFACE" ] ; then + ethernet_connected=$(cat /sys/class/net/$EIFACE/carrier) + if [[ "$ethernet_connected" != "0" ]]; then + echo $'Trying ethernet bridge to the internet' + ifconfig $EIFACE up promisc + echo $'End of ethernet bridge' + else + echo $"$EIFACE is not connected" + fi + fi + + enable_mesh_seconary_wifi + + enable_mesh_firewall + + systemctl restart avahi-daemon + + enable_mesh_scuttlebot + enable_mesh_tor + + + sed -i "s|server_name .*|server_name ${HOSTNAME}.local;|g" /etc/nginx/sites-available/git_ssb + + systemctl restart nginx + + verify +} + +function monitor { + if [ -z "$IFACE" ] ; then + echo 'error: unable to find wifi interface, not enabling BMX6 mesh' + exit 723657 + fi + + clear + echo '' + echo $'*** Stopping network ***' + echo '' + + stop + + echo "info: monitoring mesh network $WIFI_SSID on $IFACE" + + systemctl stop network-manager + sleep 5 + + clear + echo '' + echo $'*** Setting firewall rate limit ***' + echo '' + + global_rate_limit + + clear + echo '' + echo $'*** Enabling wifi adaptor in monitor mode ***' + echo '' + + # Might have to re-enable wifi + rfkill unblock $(rfkill list|awk -F: "/phy/ {print $1}") || true + + ifconfig $IFACE down + ifconfig $IFACE mtu 1500 + ifconfig $IFACE hw ether $(assign_peer_address) + iwconfig $IFACE enc off + iwconfig $IFACE mode monitor channel $CHANNEL + sleep 1 + iwconfig $IFACE ap $CELLID + + ifconfig $IFACE up + + horst -i $IFACE + + clear + echo '' + echo $'*** Restarting the network daemon. This may take a while. ***' + echo '' + + start +} + +if ! grep -q "$IFACE" /proc/net/dev; then + echo 'Interface $IFACE was not found' + stop + exit 1 +fi + +case "$1" in + start|stop|status|monitor) + $1 + ;; + restart) + clear + echo '' + echo $'*** Stopping BMX6 mesh network connection ***' + echo '' + stop + sleep 10 + clear + echo '' + echo $'*** Starting BMX6 mesh network connection ***' + echo '' + start + ;; + ping) + ping $2 + ;; + data) + bmx6 -lc traffic=$IFACE + ;; + ls|list) + avahi-browse -atl + ;; + *) + echo "error: invalid parameter $1" + echo 'usage: $0 {start|stop|restart|status|ping|ls|list}' + exit 2 + ;; +esac +exit 0 diff --git a/src/freedombone-utils-mesh b/src/freedombone-utils-mesh new file mode 100755 index 00000000..abcdbf1e --- /dev/null +++ b/src/freedombone-utils-mesh @@ -0,0 +1,343 @@ +#!/bin/bash +# +# .---. . . +# | | | +# |--- .--. .-. .-. .-.| .-. .--.--. |.-. .-. .--. .-. +# | | (.-' (.-' ( | ( )| | | | )( )| | (.-' +# ' ' --' --' -' - -' ' ' -' -' -' ' - --' +# +# Freedom in the Cloud +# +# mesh utilities used by the batman and bmx commands +# +# License +# ======= +# +# Copyright (C) 2018 Bob Mottram <bob@freedombone.net> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +if [[ $1 == "start" ]]; then + # install avahi + sed -i "s|#host-name=.*|host-name=$(hostname)|g" /etc/avahi/avahi-daemon.conf + sed -i "s|host-name=.*|host-name=$(hostname)|g" /etc/avahi/avahi-daemon.conf + sed -i "s|use-ipv4=.*|use-ipv4=yes|g" /etc/avahi/avahi-daemon.conf + sed -i "s|use-ipv6=.*|use-ipv6=no|g" /etc/avahi/avahi-daemon.conf + sed -i "s|#disallow-other-stacks=.*|disallow-other-stacks=yes|g" /etc/avahi/avahi-daemon.conf + sed -i "s|hosts:.*|hosts: files mdns4_minimal dns mdns4 mdns|g" /etc/nsswitch.conf +fi + +# Mesh definition +WIFI_SSID='mesh' +if [ -f $COMPLETION_FILE ]; then + if grep -q "WIFI_SSID:" $COMPLETION_FILE; then + WIFI_SSID=$(cat $COMPLETION_FILE | grep "WIFI_SSID:" | awk -F ':' '{print $2}') + fi + sed -i "s|WIFI_SSID:.*|WIFI_SSID:${WIFI_SSID}|g" $COMPLETION_FILE +fi +CELLID='any' + +CHANNEL=2 +HOTSPOT_CHANNEL=6 +if [ -f $COMPLETION_FILE ]; then + if grep -q "Wifi channel:" $COMPLETION_FILE; then + CHANNEL=$(cat $COMPLETION_FILE | grep "Wifi channel:" | awk -F ':' '{print $2}') + fi + sed -i "s|Wifi channel:.*|Wifi channel:${CHANNEL}|g" $COMPLETION_FILE +fi + +ZERONET_PORT=15441 +IPFS_PORT=4001 +TOX_PORT=33445 +TRACKER_PORT=6969 +LIBREVAULT_PORT=42345 +TAHOELAFS_PORT=50213 +GIT_SSB_PORT=7718 +NGINX_GIT_SSB_PORT=7719 + +# Ethernet bridge definition (bridged to bat0) +BRIDGE=br-mesh +BRIDGE_HOTSPOT=br-hotspot +IFACE= +IFACE_SECONDARY= +EIFACE=eth0 +WLAN_ADAPTORS=$(count_wlan) + +if [ $WLAN_ADAPTORS -eq 0 ]; then + echo $'No wlan adaptors found' + exit 0 +fi + +function get_ipv4_wlan { + echo $(ip -o -f inet addr show dev "$IFACE" | awk '{print $4}' | awk 'END {print}' | awk -F '/' '{print $1}') +} + +function mesh_hotspot_ip_address { + echo $(ip -o -f inet addr show dev "${BRIDGE}" | awk '{print $4}' | awk 'END {print}' | awk -F '/' '{print $1}') +} + +function global_rate_limit { + if ! grep -q "tcp_challenge_ack_limit" /etc/sysctl.conf; then + echo 'net.ipv4.tcp_challenge_ack_limit = 999999999' >> /etc/sysctl.conf + else + sed -i 's|net.ipv4.tcp_challenge_ack_limit.*|net.ipv4.tcp_challenge_ack_limit = 999999999|g' /etc/sysctl.conf + fi + sysctl -p -q +} + +function assign_peer_address { + for i in {1..6}; do + number=$RANDOM + let "number %= 255" + octet=$(echo "obase=16;$number" | bc) + if [ ${#octet} -lt 2 ]; then + octet="0${octet}" + fi + if [ $i -gt 1 ]; then + echo -n ":" + fi + echo -n "${octet}" + done +} + +function mesh_create_app_downloads_page { + if [ ! -d /root/$PROJECT_NAME/image_build/mesh_apps ]; then + return + fi + if [ ! -d /var/www/html ]; then + return + fi + # Don't go straight to cryptpad when navigating to the peer's IP address + if [ -L /etc/nginx/sites-enabled/cryptpad ]; then + rm /etc/nginx/sites-enabled/cryptpad + ln -s /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default + if [ -d /etc/cryptpad ]; then + systemctl stop cryptpad + systemctl disable cryptpad + fi + systemctl restart nginx + fi + # Don't show the cryptpad icon on the desktop + if [ -f /home/fbone/Desktop/cryptpad.desktop ]; then + mv /home/fbone/Desktop/cryptpad.desktop /home/fbone/.cryptpad.desktop + fi + + cp /root/$PROJECT_NAME/website/EN/meshindex.html /var/www/html/index.html + if [ ! -f /var/www/html/ssb.apk ]; then + cp /root/$PROJECT_NAME/image_build/mesh_apps/ssb.apk /var/www/html/ssb.apk + fi + if [ ! -f /var/www/html/trifa.apk ]; then + cp /root/$PROJECT_NAME/image_build/mesh_apps/trifa.apk /var/www/html/trifa.apk + fi + if [ ! -d /var/www/html/images ]; then + mkdir /var/www/html/images + fi + if [ ! -f /var/www/html/images/logo.png ]; then + cp /root/$PROJECT_NAME/img/logo.png /var/www/html/images/logo.png + fi + if [ ! -f /var/www/html/images/ssb.png ]; then + cp /root/$PROJECT_NAME/img/icon_patchwork.png /var/www/html/images/ssb.png + fi + if [ ! -f /var/www/html/images/trifa.png ]; then + cp /root/$PROJECT_NAME/img/trifa.png /var/www/html/images/trifa.png + fi + if [ ! -f /var/www/html/freedombone.css ]; then + cp /root/$PROJECT_NAME/website/freedombone.css /var/www/html/freedombone.css + fi + chown -R www-data:www-data /var/www/html/* +} + +function enable_mesh_firewall { + iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT + iptables -A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT + iptables -A INPUT -p tcp --dport $TRACKER_PORT -j ACCEPT + iptables -A INPUT -p udp --dport $TRACKER_PORT -j ACCEPT + iptables -A INPUT -p tcp --dport 80 -j ACCEPT + iptables -A INPUT -p udp --dport 80 -j ACCEPT + iptables -A INPUT -p tcp --dport 548 -j ACCEPT + iptables -A INPUT -p udp --dport 548 -j ACCEPT + iptables -A INPUT -p tcp --dport 5353 -j ACCEPT + iptables -A INPUT -p udp --dport 5353 -j ACCEPT + iptables -A INPUT -p tcp --dport 5354 -j ACCEPT + iptables -A INPUT -p udp --dport 5354 -j ACCEPT + iptables -A INPUT -p tcp --dport $ZERONET_PORT -j ACCEPT + iptables -A INPUT -p udp --dport $ZERONET_PORT -j ACCEPT + iptables -A INPUT -p tcp --dport $IPFS_PORT -j ACCEPT + iptables -A INPUT -p tcp --dport $TOX_PORT -j ACCEPT + iptables -A INPUT -p udp --dport $TOX_PORT -j ACCEPT + iptables -A INPUT -p tcp --dport $LIBREVAULT_PORT -j ACCEPT + iptables -A INPUT -p udp --dport $LIBREVAULT_PORT -j ACCEPT + iptables -A INPUT -p tcp --dport $TAHOELAFS_PORT -j ACCEPT + # SSB/Scuttlebot/Patchwork + iptables -A INPUT -p tcp --dport $GIT_SSB_PORT -j ACCEPT + iptables -A INPUT -p udp --dport 8008 -j ACCEPT + iptables -A INPUT -p tcp --dport 8008 -j ACCEPT + iptables -A INPUT -p udp --dport 8010 -j ACCEPT + iptables -A INPUT -p tcp --dport 8010 -j ACCEPT + # vpn over the internet + # Note: the vpn firewall settings are needed in order for Patchwork + # to discover local peers + iptables -A INPUT -p tcp --dport 653 -j ACCEPT + iptables -A INPUT -p udp --dport 653 -j ACCEPT + iptables -A INPUT -i ${EIFACE} -m state --state NEW -p tcp --dport 1194 -j ACCEPT + iptables -A INPUT -i tun+ -j ACCEPT + iptables -A FORWARD -i tun+ -j ACCEPT + iptables -A FORWARD -i tun+ -o ${EIFACE} -m state --state RELATED,ESTABLISHED -j ACCEPT + iptables -A FORWARD -i ${EIFACE} -o tun+ -m state --state RELATED,ESTABLISHED -j ACCEPT + iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o ${EIFACE} -j MASQUERADE + iptables -A OUTPUT -o tun+ -j ACCEPT + echo 1 > /proc/sys/net/ipv4/ip_forward + sed -i 's|# net.ipv4.ip_forward|net.ipv4.ip_forward|g' /etc/sysctl.conf + sed -i 's|#net.ipv4.ip_forward|net.ipv4.ip_forward|g' /etc/sysctl.conf + sed -i 's|net.ipv4.ip_forward.*|net.ipv4.ip_forward=1|g' /etc/sysctl.conf +} + +function disable_mesh_firewall { + iptables -D INPUT -p tcp --dport $TRACKER_PORT -j ACCEPT + iptables -D INPUT -p udp --dport $TRACKER_PORT -j ACCEPT + iptables -D INPUT -p tcp --dport 80 -j ACCEPT + iptables -D INPUT -p udp --dport 80 -j ACCEPT + iptables -D INPUT -p tcp --dport 548 -j ACCEPT + iptables -D INPUT -p udp --dport 548 -j ACCEPT + iptables -D INPUT -p tcp --dport 5353 -j ACCEPT + iptables -D INPUT -p udp --dport 5353 -j ACCEPT + iptables -D INPUT -p tcp --dport 5354 -j ACCEPT + iptables -D INPUT -p udp --dport 5354 -j ACCEPT + iptables -D INPUT -p tcp --dport $ZERONET_PORT -j ACCEPT + iptables -D INPUT -p udp --dport $ZERONET_PORT -j ACCEPT + iptables -D INPUT -p tcp --dport $IPFS_PORT -j ACCEPT + iptables -D INPUT -p udp --dport $IPFS_PORT -j ACCEPT + iptables -D INPUT -p tcp --dport $TOX_PORT -j ACCEPT + iptables -D INPUT -p udp --dport $TOX_PORT -j ACCEPT + iptables -D INPUT -p tcp --dport $LIBREVAULT_PORT -j ACCEPT + iptables -D INPUT -p udp --dport $LIBREVAULT_PORT -j ACCEPT + iptables -D INPUT -p tcp --dport $TAHOELAFS_PORT -j ACCEPT + # SSB/Scuttlebot/Patchwork + iptables -D INPUT -p tcp --dport $GIT_SSB_PORT -j ACCEPT + iptables -D INPUT -p udp --dport 8008 -j ACCEPT + iptables -D INPUT -p tcp --dport 8008 -j ACCEPT + iptables -D INPUT -p udp --dport 8010 -j ACCEPT + iptables -D INPUT -p tcp --dport 8010 -j ACCEPT + # vpn over the internet + iptables -D INPUT -p tcp --dport 653 -j ACCEPT + iptables -D INPUT -p udp --dport 653 -j ACCEPT + iptables -D INPUT -i ${EIFACE} -m state --state NEW -p tcp --dport 1194 -j ACCEPT + iptables -D INPUT -i tun+ -j ACCEPT + iptables -D FORWARD -i tun+ -j ACCEPT + iptables -D FORWARD -i tun+ -o ${EIFACE} -m state --state RELATED,ESTABLISHED -j ACCEPT + iptables -D FORWARD -i ${EIFACE} -o tun+ -m state --state RELATED,ESTABLISHED -j ACCEPT + iptables -t nat -D POSTROUTING -s 10.8.0.0/24 -o ${EIFACE} -j MASQUERADE + iptables -D OUTPUT -o tun+ -j ACCEPT + + echo 0 > /proc/sys/net/ipv4/ip_forward + sed -i 's|net.ipv4.ip_forward=.*|net.ipv4.ip_forward=0|g' /etc/sysctl.conf +} + +function enable_mesh_scuttlebot { + if [ -f /etc/scuttlebot/.ssb/config ]; then + ethernet_connected=$(cat /sys/class/net/eth0/carrier) + if [[ "$ethernet_connected" != "0" ]]; then + sed -i "s|\"host\": .*|\"host\": \"$(get_ipv4_wlan)\",|g" /etc/scuttlebot/.ssb/config + systemctl restart scuttlebot + else + if [ ! -f /etc/nginx/sites-available/git_ssb ]; then + systemctl stop scuttlebot + else + systemctl restart scuttlebot + fi + fi + fi + sed -i "s|\"host\":.*|\"host\": \"${HOSTNAME}.local\",|g" /etc/scuttlebot/.ssb/config + systemctl restart scuttlebot +} + +function enable_mesh_tor { + # if we have an ethernet connection to an internet router then create + # an onion address for this peer + if [[ "$ethernet_connected" != "0" ]]; then + systemctl enable tor + systemctl start tor + HIDDEN_SERVICE_PATH=/var/lib/tor/hidden_service_ + if [ ! -f ${HIDDEN_SERVICE_PATH}mesh/hostname ]; then + echo "HiddenServiceDir ${HIDDEN_SERVICE_PATH}mesh/" >> /etc/tor/torrc + echo "HiddenServicePort 653 127.0.0.1:653" >> /etc/tor/torrc + systemctl restart tor + fi + else + systemctl stop tor + systemctl disable tor + fi +} + +function enable_mesh_seconary_wifi { + if [ $secondary_wifi_available ]; then + sed -i 's|#DAEMON_CONF=.*|DAEMON_CONF="/etc/hostapd/hostapd.conf"|g' /etc/default/hostapd + + mesh_hotspot_address=$(mesh_hotspot_ip_address) + if [[ "$mesh_hotspot_address" == *'.'* ]]; then + echo "interface=${IFACE_SECONDARY}" > /etc/hostapd/hostapd.conf + echo "bridge=${BRIDGE}" >> /etc/hostapd/hostapd.conf + echo 'driver=nl80211' >> /etc/hostapd/hostapd.conf + echo "country_code=UK" >> /etc/hostapd/hostapd.conf + echo "ssid=${WIFI_SSID}-${mesh_hotspot_address}" >> /etc/hostapd/hostapd.conf + echo 'hw_mode=g' >> /etc/hostapd/hostapd.conf + echo "channel=${HOTSPOT_CHANNEL}" >> /etc/hostapd/hostapd.conf + echo 'wpa=2' >> /etc/hostapd/hostapd.conf + echo "wpa_passphrase=$HOTSPOT_PASSPHRASE" >> /etc/hostapd/hostapd.conf + echo 'wpa_key_mgmt=WPA-PSK' >> /etc/hostapd/hostapd.conf + echo 'wpa_pairwise=TKIP' >> /etc/hostapd/hostapd.conf + echo 'rsn_pairwise=CCMP' >> /etc/hostapd/hostapd.conf + echo 'auth_algs=1' >> /etc/hostapd/hostapd.conf + echo 'macaddr_acl=0' >> /etc/hostapd/hostapd.conf + + sed -i "s|#interface=.*|interface=${IFACE_SECONDARY}|g" /etc/dnsmasq.conf + sed -i "s|interface=.*|interface=${IFACE_SECONDARY}|g" /etc/dnsmasq.conf + sed -i "s|listen-address=.*|listen-address=127.0.0.1,$mesh_hotspot_address|g" /etc/dnsmasq.conf + sed -i 's|#listen-address|listen-address|g' /etc/dnsmasq.conf + systemctl enable dnsmasq + systemctl restart dnsmasq + + systemctl enable hostapd + systemctl restart hostapd + mesh_create_app_downloads_page + else + secondary_wifi_available= + echo $'WARNING: No IP address could be obtained for the hotspot' + fi + fi + + if [ ! $secondary_wifi_available ]; then + systemctl stop hostapd + systemctl disable hostapd + + # Recreate the cryptpad symlink + if [ -f /etc/nginx/sites-available/cryptpad ]; then + if [ -L /etc/nginx/sites-enabled/cryptpad ]; then + rm /etc/nginx/sites-enabled/default + fi + systemctl enable cryptpad + systemctl start cryptpad + + if [ ! -L /etc/nginx/sites-enabled/cryptpad ]; then + ln -s /etc/nginx/sites-available/cryptpad /etc/nginx/sites-enabled/cryptpad + systemctl restart nginx + fi + fi + if [ -f /home/fbone/.cryptpad.desktop ]; then + mv /home/fbone/.cryptpad.desktop /home/fbone/Desktop/cryptpad.desktop + fi + fi +} + +# NOTE: deliberately there is no "exit 0"