diff --git a/conf/dhcpd.conf b/conf/dhcpd.conf new file mode 100644 index 0000000..08f8064 --- /dev/null +++ b/conf/dhcpd.conf @@ -0,0 +1,15 @@ +option domain-name-servers , ; +default-lease-time 14440; +ddns-update-style none; +deny bootp; + +shared-network { + subnet .0 + netmask 255.255.255.0 { + option routers .1; + option subnet-mask 255.255.255.0; + pool { + range .2 .254; + } + } +} diff --git a/conf/hostapd.conf b/conf/hostapd.conf new file mode 100644 index 0000000..6e1d677 --- /dev/null +++ b/conf/hostapd.conf @@ -0,0 +1,12 @@ +interface= +ssid= +hw_mode=g +channel=6 +macaddr_acl=0 +auth_algs=1 +ignore_broadcast_ssid=0 +wpa=2 +wpa_passphrase= +wpa_key_mgmt=WPA-PSK +wpa_pairwise=TKIP +rsn_pairwise=CCMP diff --git a/conf/radvd.conf b/conf/radvd.conf new file mode 100644 index 0000000..a99dadd --- /dev/null +++ b/conf/radvd.conf @@ -0,0 +1,6 @@ +interface +{ + AdvSendAdvert on; + prefix /64 { }; + RDNSS { }; +}; diff --git a/conf/ynh-hotspot b/conf/ynh-hotspot new file mode 100644 index 0000000..ac1e067 --- /dev/null +++ b/conf/ynh-hotspot @@ -0,0 +1,215 @@ +#!/bin/bash +### BEGIN INIT INFO +# Provides: ynh-hotspot +# Required-Start: $network $remote_fs $syslog +# Required-Stop: $network $remote_fs $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Set prerequisites for wifi hotspot. +# Description: Set prerequisites for wifi hotspot. +### END INIT INFO + +is_ndproxy_set() { + proxy=$(ip -6 neigh show proxy) + [ ! -z "${proxy}" ] +} + +is_nat_set() { + iptables -nt nat -L POSTROUTING | grep -q MASQUERADE +} + +is_ip4nataddr_set() { + ip a s dev | grep -q .1/24 +} + +is_ip6addr_set() { + ip a s dev | grep -q /64 +} + +is_forwarding_set() { + ip6=$(sysctl net.ipv6.conf.all.forwarding | awk '{ print $NF; }') + ip4=$(sysctl net.ipv4.conf.all.forwarding | awk '{ print $NF; }') + [ ${ip6} -eq 1 -a ${ip4} -eq 1 ] +} + +is_hostapd_running() { + service hostapd status &> /dev/null +} + +is_radvd_running() { + service radvd status &> /dev/null +} + +is_dhcpd_running() { + service isc-dhcp-server status &> /dev/null +} + +is_running() { + is_ndproxy_set && is_nat_set && is_forwarding_set\ + && is_hostapd_running && is_radvd_running && is_dhcpd_running +} + +case "$1" in + start) + if is_running; then + echo "Already correctly set" + else + if ! is_ndproxy_set; then + echo "Set NDP proxy" + ip -6 neigh add proxy dev + fi + + if ! is_nat_set; then + echo "Set NAT" + iptables -t nat -A POSTROUTING -o -j MASQUERADE + fi + + if ! is_ip4nataddr_set; then + echo "Set IPv4 NAT address" + ip a a .1/24 dev + fi + + if ! is_ip6addr_set; then + echo "Set IPv6 address" + ip a a /64 dev + fi + + if ! is_forwarding_set; then + echo "Set forwarding" + sysctl -w net.ipv6.conf.all.forwarding=1 &> /dev/null + sysctl -w net.ipv4.conf.all.forwarding=1 &> /dev/null + fi + + if ! is_hostapd_running; then + echo "Run hostapd" + service hostapd start + fi + + # must be running after hostapd + if ! is_radvd_running; then + echo "Run radvd" + sleep 1 + service radvd start + fi + + # "options routers" addr (is_ip6addr_set) must be set before + if ! is_dhcpd_running; then + echo "Run dhcpd" + service isc-dhcp-server start + fi + fi + ;; + stop) + if is_ndproxy_set; then + echo "Unset NDP proxy" + ip -6 neigh del proxy dev + fi + + if is_nat_set; then + echo "Unset NAT" + iptables -t nat -D POSTROUTING -o -j MASQUERADE + fi + + if is_ip4nataddr_set; then + echo "Unset IPv4 NAT address" + ip a d .1/24 dev + fi + + if is_ip6addr_set; then + echo "Unset IPv6 address" + ip a d /64 dev + fi + + if is_forwarding_set; then + echo "Unset forwarding" + sysctl -w net.ipv6.conf.all.forwarding=0 &> /dev/null + sysctl -w net.ipv4.conf.all.forwarding=0 &> /dev/null + fi + + if is_hostapd_running; then + echo "Stop hostapd" + service hostapd stop + fi + + if is_radvd_running; then + echo "Stop radvd" + service radvd stop + fi + + if is_dhcpd_running; then + echo "Stop dhcpd" + service isc-dhcp-server stop + fi + ;; + restart) + $0 stop + $0 start + ;; + status) + exitcode=0 + + if is_ndproxy_set; then + echo "NDP proxy is correctly set" + else + echo "NDP proxy is NOT set" + exitcode=1 + fi + + if is_nat_set; then + echo "NAT is correctly set" + else + echo "NAT is NOT set" + exitcode=1 + fi + + if is_ip4nataddr_set; then + echo "IPv4 NAT address is correctly set" + else + echo "IPv4 NAT address is NOT set" + exitcode=1 + fi + + if is_ip6addr_set; then + echo "IPv6 address is correctly set" + else + echo "IPv6 address is NOT set" + exitcode=1 + fi + + if is_forwarding_set; then + echo "Forwarding is correctly set" + else + echo "Forwarding is NOT set" + exitcode=1 + fi + + if is_hostapd_running; then + echo "Hostapd is running" + else + echo "Hostapd is NOT running" + exitcode=1 + fi + + if is_radvd_running; then + echo "Radvd is running" + else + echo "Radvd is NOT running" + exitcode=1 + fi + + if is_dhcpd_running; then + echo "Dhcpd is running" + else + echo "Dhcpd is NOT running" + exitcode=1 + fi + + exit ${exitcode} + ;; + *) + echo "Usage: $0 {start|stop|restart|status}" + exit 1 + ;; +esac + +exit 0 diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..22cbe28 --- /dev/null +++ b/manifest.json @@ -0,0 +1,89 @@ +{ + "name": "Wifi Hotspot", + "id": "hotspot", + "description": { + "en": "Wifi Hotspot", + "fr": "Hotspot Wifi" + }, + "license": "AGPL-3", + "developer": { + "name": "Julien Vaubourg", + "email": "julien@vaubourg.com", + "url": "http://julien.vaubourg.com" + }, + "multi_instance": "false", + "arguments": { + "install" : [ + { + "name": "Wifi SSID", + "ask": { + "en": "Choose an SSID" + }, + "example": "myNeutralNetwork", + "default": "myNeutralNetwork" + }, + { + "name": "Wifi passphrase", + "ask": { + "en": "Choose a WPA2 passphrase (at least 8 chars)" + }, + "example": "VhegT8oev0jZI" + }, + { + "name": "Wifi device", + "ask": { + "en": "Select your wifi interface (hotspot side)" + }, + "example": "wlan0", + "default": "wlan0" + }, + { + "name": "Wired device", + "ask": { + "en": "Select your wired interface (internet side)" + }, + "example": "eth0", + "default": "eth0" + }, + { + "name": "IPv6 network", + "ask": { + "en": "Select your IPv6 delegated network (netmask number must be <= 64)" + }, + "example": "2001:db8:42::/48" + }, + { + "name": "First IPv6 DNS resolver", + "ask": { + "en": "Select a first IPv6 DNS resolver" + }, + "example": "2001:913::8", + "default": "2001:913::8" + }, + { + "name": "Second IPv6 DNS resolver", + "ask": { + "en": "Select a second IPv6 DNS resolver" + }, + "example": "2001:910:800::40", + "default": "2001:910:800::40" + }, + { + "name": "First IPv4 DNS resolver", + "ask": { + "en": "Select a first IPv4 DNS resolver" + }, + "example": "80.67.188.188", + "default": "80.67.188.188" + }, + { + "name": "Second IPv4 DNS resolver", + "ask": { + "en": "Select a second IPv4 DNS resolver" + }, + "example": "80.67.169.12", + "default": "80.67.169.12" + } + ] + } +} diff --git a/scripts/install b/scripts/install new file mode 100644 index 0000000..a8ca165 --- /dev/null +++ b/scripts/install @@ -0,0 +1,96 @@ +#!/bin/bash + +# Retrieve arguments +wifi_ssid=$1 +wifi_passphrase=$2 +wifi_device=$3 +wired_device=$4 +ip6_net=$5 +ip6_dns0=$6 +ip6_dns1=$7 +ip4_dns0=$8 +ip4_dns1=$9 + +# Check arguments +# TODO + +# Save arguments for future upgrades +sudo yunohost app setting hotspot wifi_ssid -v $wifi_ssid +sudo yunohost app setting hotspot wifi_passphrase -v $wifi_passphrase +sudo yunohost app setting hotspot wifi_device -v $wifi_device +sudo yunohost app setting hotspot wired_device -v $wired_device +sudo yunohost app setting hotspot ip6_net -v $ip6_net +sudo yunohost app setting hotspot ip6_dns0 -v $ip6_dns0 +sudo yunohost app setting hotspot ip6_dns1 -v $ip6_dns1 +sudo yunohost app setting hotspot ip4_dns0 -v $ip4_dns0 +sudo yunohost app setting hotspot ip4_dns1 -v $ip4_dns1 + +# Install packages +sudo apt-get --assume-yes --force-yes install hostapd radvd isc-dhcp-server + +# Install extra packages +sudo apt-get --assume-yes --force-yes install sipcalc + +# Compute extra arguments +ip6_expanded_net=$(sipcalc ${ip6_net} | grep Expanded | awk '{ print $NF; }') +ip6_net=$(sipcalc ${ip6_net} | grep Compressed | awk '{ print $NF; }') +ip6_addr=$(echo "$(echo ${ip6_expanded_net} | cut -d: -f1-7):42") +ip6_addr=$(sipcalc ${ip6_addr} | grep Compressed | awk '{ print $NF; }') +ip4_nat_prefix=10.0.242 + +# Copy confs +sudo install -b -o root -g root -m 0644 ../conf/hostapd.conf /etc/hostapd/ +sudo install -b -o root -g root -m 0644 ../conf/radvd.conf /etc/ +sudo install -b -o root -g root -m 0644 ../conf/dhcpd.conf /etc/dhcp/ + +# Fix confs +## hostapd +sudo sed "s||${wifi_device}|g" -i /etc/hostapd/hostapd.conf +sudo sed "s||${wifi_ssid}|g" -i /etc/hostapd/hostapd.conf +sudo sed "s||${wifi_passphrase}|g" -i /etc/hostapd/hostapd.conf + +## radvd +sudo sed "s||${wifi_device}|g" -i /etc/radvd.conf +sudo sed "s||${ip6_net}|g" -i /etc/radvd.conf +sudo sed "s||${ip6_dns0}|g" -i /etc/radvd.conf +sudo sed "s||${ip6_dns1}|g" -i /etc/radvd.conf + +## dhcpd +sudo sed "s||${ip4_dns0}|g" -i /etc/dhcp/dhcpd.conf +sudo sed "s||${ip4_dns1}|g" -i /etc/dhcp/dhcpd.conf +sudo sed "s||${wifi_device}|g" -i /etc/dhcp/dhcpd.conf +sudo sed "s||${ip4_nat_prefix}|g" -i /etc/dhcp/dhcpd.conf + +# Copy init script +sudo install -b -o root -g root -m 0755 ../conf/ynh-hotspot /etc/init.d/ + +# Fix init script +## ynh-hostspot +sudo sed "s||${ip6_addr}|g" -i /etc/init.d/ynh-hotspot +sudo sed "s||${ip4_nat_prefix}|g" -i /etc/init.d/ynh-hotspot +sudo sed "s||${wifi_device}|g" -i /etc/init.d/ynh-hotspot +sudo sed "s||${wired_device}|g" -i /etc/init.d/ynh-hotspot + +## hostapd +sudo sed 's|^DAEMON_CONF=$|&/etc/hostapd/hostapd.conf|' -i /etc/init.d/hostapd + +# Set default inits +# The boot order of these services are important, so they are disabled by default +# and the ynh-hotspot service handles them. +# All services are registred by yunohost in order to prevent conflicts after the uninstall. +sudo yunohost service add isc-dhcp-server +sudo yunohost service stop isc-dhcp-server +sudo yunohost service disable isc-dhcp-server +sudo yunohost service add radvd +sudo yunohost service stop radvd +sudo yunohost service disable radvd +sudo yunohost service add hostapd +sudo yunohost service stop hostapd +sudo yunohost service disable hostapd + +# Gooo +sudo yunohost service add ynh-hotspot +sudo yunohost service enable ynh-hotspot +sudo yunohost service start ynh-hotspot + +exit 0 diff --git a/scripts/remove b/scripts/remove new file mode 100644 index 0000000..2524213 --- /dev/null +++ b/scripts/remove @@ -0,0 +1,16 @@ +#!/bin/bash + +# The End +sudo yunohost service stop ynh-hotspot +sudo yunohost service remove ynh-hotspot +sudo rm -f /etc/init.d/ynh-hotspot + +# Remove confs +sudo rm -rf /etc/hostapd/ /etc/radvd.conf /etc/dhcp/dhcpd.conf + +# Remove packets +# The yunohost policy is currently to not uninstall packets (dependency problems) +## sudo apt-get --assume-yes --force-yes remove hostapd radvd isc-dhcp-server +## sudo apt-get --assume-yes --force-yes remove sipcalc + +exit 0