1
0
Fork 0
mirror of https://github.com/YunoHost-Apps/hotspot_ynh.git synced 2024-09-03 19:25:53 +02:00

DHCP with dnsmasq

This commit is contained in:
Julien VAUBOURG 2014-12-26 18:58:58 +01:00
parent aa2ae5853f
commit a72fcd29f8
12 changed files with 175 additions and 113 deletions

View file

@ -16,7 +16,7 @@ See the <a href="https://raw.githubusercontent.com/jvaubourg/hotspot_ynh/master/
* WPA2 encryption
* 802.11n compliant
* IPv6 compliant (with a delegated prefix)
* Automatic clients configuration (IPv6 and IPv4)
* Announce DNS resolvers (IPv6 and IPv4)
* Announce DNS resolvers (IPv6 with RDNSS/DHCPv6 and IPv4 with DHCPv4)
* Automatic clients configuration (IPv6 with SLAAC/DHCPv6 and IPv4 with DHCPv4)
* Set an IPv6 from your delegated prefix (*prefix::42*) on the server, to use for the AAAA records
* Web interface ([screenshot](https://raw.githubusercontent.com/jvaubourg/hotspot_ynh/master/screenshot.png))

View file

@ -1,15 +0,0 @@
option domain-name-servers <TPL:IP4_DNS0>, <TPL:IP4_DNS1>;
default-lease-time 14440;
ddns-update-style none;
deny bootp;
shared-network <TPL:WIFI_DEVICE> {
subnet <TPL:IP4_NAT_PREFIX>.0
netmask 255.255.255.0 {
option routers <TPL:IP4_NAT_PREFIX>.1;
option subnet-mask 255.255.255.0;
pool {
range <TPL:IP4_NAT_PREFIX>.2 <TPL:IP4_NAT_PREFIX>.254;
}
}
}

View file

@ -0,0 +1,30 @@
# Do DHCP for this subnet.
dhcp-range=interface:<TPL:WIFI_DEVICE>,<TPL:IP4_NAT_PREFIX>.2,<TPL:IP4_NAT_PREFIX>.254,4h
# Send DHCPv4 option.
dhcp-option=option:dns-server,<TPL:IP4_DNS0>,<TPL:IP4_DNS1>
# Set the DHCP server to authoritative mode. In this mode it will barge in
# and take over the lease for any client which broadcasts on the network,
# whether it has a record of the lease or not. This avoids long timeouts
# when a machine wakes up on a new network. DO NOT enable this if there's
# the slightest chance that you might end up accidentally configuring a DHCP
# server for your campus/company accidentally. The ISC server uses
# the same option, and this URL provides more information:
# http://www.isc.org/files/auth.html
dhcp-authoritative
# On systems which support it, dnsmasq binds the wildcard address,
# even when it is listening on only some interfaces. It then discards
# requests that it shouldn't reply to. This has the advantage of
# working even when interfaces come and go and change address. If you
# want dnsmasq to really bind only the interfaces it is listening on,
# uncomment this option. About the only time you may need this is when
# running another nameserver on the same machine.
bind-interfaces
# If this line is uncommented, dnsmasq will read /etc/ethers and act
# on the ethernet-address/IP pairs found there just as if they had
# been given as --dhcp-host options. Useful if you keep
# MAC-address/host mappings there for other purposes.
#read-ethers

View file

@ -0,0 +1,6 @@
# Do DHCP and Router Advertisements for this subnet. Set the A bit in the RA
# so that clients can use SLAAC addresses as well as DHCP ones.
dhcp-range=interface:<TPL:WIFI_DEVICE>,<TPL:IP6_NET>,slaac,64,4h
# Send DHCPv6 option. Note [] around IPv6 addresses.
dhcp-option=option6:dns-server,[<TPL:IP6_DNS0>],[<TPL:IP6_DNS1>]

View file

@ -46,22 +46,39 @@ is_forwarding_set() {
[ "${ip6}" -eq 1 -a "${ip4}" -eq 1 ]
}
is_dhcpdv6_set() {
[ -e /etc/dnsmasq.d/dhcpdv6.conf ]
}
is_dhcpdv4_set() {
[ -e /etc/dnsmasq.d/dhcpdv4.conf ]
}
is_hostapd_running() {
service hostapd status &> /dev/null
if [ $? -eq 0 ]; then
# If the wifi antenna was unplugged
if ip link show dev "${ynh_wifi_device}" | grep -q DOWN; then
service hostapd stop &> /dev/null
return 1
fi
return 0
fi
return 1
}
is_radvd_running() {
service radvd status &> /dev/null
}
is_dhcpd_running() {
service isc-dhcp-server status &> /dev/null
is_dnsmasq_running() {
service dnsmasq status &> /dev/null
}
is_running() {
( has_ip6delegatedprefix && is_ip6addr_set && is_radvd_running && is_ndproxy_set || ! has_ip6delegatedprefix )\
( has_ip6delegatedprefix && is_ip6addr_set && is_ndproxy_set && is_dhcpdv6_set || ! has_ip6delegatedprefix )\
&& is_nat_set "${new_internet_device}" && is_ip4nataddr_set && is_forwarding_set && is_hostapd_running\
&& is_dhcpd_running
&& is_dhcpdv4_set && is_dnsmasq_running
}
## Setters
@ -90,6 +107,26 @@ set_forwarding() {
sysctl -w net.ipv4.conf.all.forwarding=1 > /dev/null
}
set_dhcpd() {
if has_ip6delegatedprefix; then
cp /etc/dnsmasq.d.tpl/dhcpdv6.conf.tpl /etc/dnsmasq.d/dhcpdv6.conf
sed "s|<TPL:WIFI_DEVICE>|${ynh_wifi_device}|g" -i /etc/dnsmasq.d/dhcpdv6.conf
sed "s|<TPL:IP6_NET>|${ynh_ip6_net}|g" -i /etc/dnsmasq.d/dhcpdv6.conf
sed "s|<TPL:IP6_DNS0>|${ynh_ip6_dns0}|g" -i /etc/dnsmasq.d/dhcpdv6.conf
sed "s|<TPL:IP6_DNS1>|${ynh_ip6_dns1}|g" -i /etc/dnsmasq.d/dhcpdv6.conf
fi
cp /etc/dnsmasq.d.tpl/dhcpdv4.conf.tpl /etc/dnsmasq.d/dhcpdv4.conf
sed "s|<TPL:IP4_DNS0>|${ynh_ip4_dns0}|g" -i /etc/dnsmasq.d/dhcpdv4.conf
sed "s|<TPL:IP4_DNS1>|${ynh_ip4_dns1}|g" -i /etc/dnsmasq.d/dhcpdv4.conf
sed "s|<TPL:WIFI_DEVICE>|${ynh_wifi_device}|g" -i /etc/dnsmasq.d/dhcpdv4.conf
sed "s|<TPL:IP4_NAT_PREFIX>|${ynh_ip4_nat_prefix}|g" -i /etc/dnsmasq.d/dhcpdv4.conf
service dnsmasq restart
}
start_hostapd() {
cp /etc/hostapd/hostapd.conf{.tpl,}
@ -107,28 +144,6 @@ start_hostapd() {
service hostapd start
}
start_radvd() {
cp /etc/radvd.conf{.tpl,}
sed "s|<TPL:WIFI_DEVICE>|${ynh_wifi_device}|g" -i /etc/radvd.conf
sed "s|<TPL:IP6_NET>|${ynh_ip6_net}|g" -i /etc/radvd.conf
sed "s|<TPL:IP6_DNS0>|${ynh_ip6_dns0}|g" -i /etc/radvd.conf
sed "s|<TPL:IP6_DNS1>|${ynh_ip6_dns1}|g" -i /etc/radvd.conf
service radvd start
}
start_dhcpd() {
cp /etc/dhcp/dhcpd.conf{.tpl,}
sed "s|<TPL:IP4_DNS0>|${ynh_ip4_dns0}|g" -i /etc/dhcp/dhcpd.conf
sed "s|<TPL:IP4_DNS1>|${ynh_ip4_dns1}|g" -i /etc/dhcp/dhcpd.conf
sed "s|<TPL:WIFI_DEVICE>|${ynh_wifi_device}|g" -i /etc/dhcp/dhcpd.conf
sed "s|<TPL:IP4_NAT_PREFIX>|${ynh_ip4_nat_prefix}|g" -i /etc/dhcp/dhcpd.conf
service isc-dhcp-server start
}
## Unsetters
unset_ndproxy() {
@ -149,6 +164,11 @@ unset_ip6addr() {
ip address delete "${ynh_ip6_addr}/64" dev "${ynh_wifi_device}"
}
unset_dhcpd() {
rm -f /etc/dnsmasq.d/dhcpdv?.conf
service dnsmasq restart
}
unset_forwarding() {
sysctl -w net.ipv6.conf.all.forwarding=0 > /dev/null
sysctl -w net.ipv4.conf.all.forwarding=0 > /dev/null
@ -158,14 +178,6 @@ stop_hostapd() {
service hostapd stop
}
stop_radvd() {
service radvd stop
}
stop_dhcpd() {
service isc-dhcp-server stop
}
## Tools
moulinette_get() {
@ -310,25 +322,16 @@ case "$1" in
set_forwarding
fi
# Run DHCP servers
if ( has_ip6delegatedprefix && ! is_dhcpdv6_set ) || ! is_dhcpdv4_set; then
echo "Set DHCP servers (dnsmasq)"
set_dhcpd
fi
# Run hostapd
if ! is_hostapd_running; then
echo "Run hostapd"
start_hostapd
sleep 1
fi
# Run radvd
# must be running after hostapd
if has_ip6delegatedprefix && ! is_radvd_running; then
echo "Run radvd"
start_radvd
fi
# Run dhcpd
# "options routers" addr (is_ip6addr_set) must be set before
if ! is_dhcpd_running; then
echo "Run dhcpd"
start_dhcpd
fi
# Update dynamic settings
@ -337,7 +340,7 @@ case "$1" in
;;
stop)
echo "[hotspot] Stopping..."
rm /tmp/.ynh-hotspot-started
rm -f /tmp/.ynh-hotspot-started
if has_ip6delegatedprefix && is_ndproxy_set; then
echo "Unset NDP proxy"
@ -364,21 +367,16 @@ case "$1" in
unset_forwarding
fi
if is_dhcpdv6_set || is_dhcpdv4_set; then
echo "Stop DHCP servers"
unset_dhcpd
fi
if is_hostapd_running; then
echo "Stop hostapd"
stop_hostapd
fi
if has_ip6delegatedprefix && is_radvd_running; then
echo "Stop radvd"
stop_radvd
fi
if is_dhcpd_running; then
echo "Stop dhcpd"
stop_dhcpd
fi
if has_vpnclient_app; then
service ynh-vpnclient start
fi
@ -406,16 +404,23 @@ case "$1" in
exitcode=1
fi
if is_radvd_running; then
echo "[OK] Radvd is running"
if is_dhcpdv6_set; then
echo "[OK] SLAAC & DHCPv6 server set"
else
echo "[ERR] Radvd is not running"
echo "[ERR] No SLAAC & DHCPv6 server set"
exitcode=1
fi
else
echo "[INFO] No IPv6 delegated prefix found"
fi
if is_dhcpdv4_set; then
echo "[OK] DHCPv4 server set"
else
echo "[ERR] No DHCPv4 server set"
exitcode=1
fi
if is_nat_set "${new_internet_device}"; then
echo "[OK] IPv4 NAT set"
else
@ -437,6 +442,13 @@ case "$1" in
exitcode=1
fi
if is_dnsmasq_running; then
echo "[OK] Dnsmasq is running"
else
echo "[ERR] Dnsmasq is not running"
exitcode=1
fi
if is_hostapd_running; then
echo "[OK] Hostapd is running"
else
@ -444,13 +456,6 @@ case "$1" in
exitcode=1
fi
if is_dhcpd_running; then
echo "[OK] Dhcpd is running"
else
echo "[ERR] Dhcpd is not running"
exitcode=1
fi
exit ${exitcode}
;;
*)

View file

@ -1,6 +0,0 @@
interface <TPL:WIFI_DEVICE>
{
AdvSendAdvert on;
prefix <TPL:IP6_NET>/64 { };
RDNSS <TPL:IP6_DNS0> <TPL:IP6_DNS1> { };
};

View file

@ -38,9 +38,7 @@ if [ ! $? -eq 0 ]; then
fi
# Install packages
# TODO: Replace isc-dhcp-server by dnsmasq (currently negotiating with the YunoHost team to
# also replace bind9 by dnsmasq)
packages='php5-fpm sipcalc hostapd radvd isc-dhcp-server iptables wireless-tools wireless-tools'
packages='php5-fpm sipcalc hostapd iptables wireless-tools'
sudo apt-get --assume-yes --force-yes install ${packages}
if [ $? -ne 0 ]; then
@ -98,9 +96,12 @@ sudo install -o root -g root -m 0755 ../conf/ipv6_expanded /usr/local/bin/
sudo install -o root -g root -m 0755 ../conf/ipv6_compressed /usr/local/bin/
# Copy confs
sudo mkdir -pm 0755 /etc/dnsmasq.d.tpl/
sudo chown root: /etc/dnsmasq.d.tpl/
sudo install -b -o root -g root -m 0644 ../conf/hostapd.conf.tpl /etc/hostapd/
sudo install -b -o root -g root -m 0644 ../conf/radvd.conf.tpl /etc/
sudo install -b -o root -g root -m 0644 ../conf/dhcpd.conf.tpl /etc/dhcp/
sudo install -b -o root -g root -m 0644 ../conf/dnsmasq_dhcpdv6.conf.tpl /etc/dnsmasq.d.tpl/dhcpdv6.conf.tpl
sudo install -b -o root -g root -m 0644 ../conf/dnsmasq_dhcpdv4.conf.tpl /etc/dnsmasq.d.tpl/dhcpdv4.conf.tpl
sudo install -b -o root -g root -m 0644 ../conf/nginx_wifiadmin.conf "/etc/nginx/conf.d/${domain}.d/wifiadmin.conf"
sudo install -b -o root -g root -m 0644 ../conf/phpfpm_wifiadmin.conf /etc/php5/fpm/pool.d/wifiadmin.conf
@ -134,18 +135,14 @@ sudo sed "s|<TPL:NGINX_LOCATION>|${url_path}|g" -i /var/www/wifiadmin/config.php
# Copy init script
sudo install -o root -g root -m 0755 ../conf/init_ynh-hotspot /etc/init.d/ynh-hotspot
# Update firewall for DHCP
sudo yunohost firewall allow --no-upnp --ipv6 UDP 547
sudo yunohost firewall allow --no-upnp UDP 67
# 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

View file

@ -9,7 +9,12 @@ sudo yunohost service remove ynh-hotspot
sudo rm -f /etc/init.d/ynh-hotspot
sudo rm -f /tmp/.ynh-hotspot-*
# Update firewall for DHCP
sudo yunohost firewall disallow --ipv6 UDP 547
sudo yunohost firewall disallow UDP 67
# Remove confs
sudo rm -fr /etc/dnsmasq.d.tpl/
sudo rm -f /etc/hostapd/hostapd.conf{.tpl,} /etc/radvd.conf{.tpl,} /etc/dhcp/dhcpd.conf{.tpl,}
sudo rm -f /etc/nginx/conf.d/${domain}.d/wifiadmin.conf
sudo rm -f /etc/php5/fpm/pool.d/wifiadmin.conf
@ -24,6 +29,6 @@ sudo rm -rf /var/www/wifiadmin/
# 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 iptables sipcalc wireless-tools
## sudo apt-get --assume-yes --force-yes remove hostapd iptables sipcalc wireless-tools
exit 0

View file

@ -42,6 +42,14 @@ function ipv6_compressed($ip) {
return $output[0];
}
function is_connected_through_hotspot($ip6_net, $ip4_nat_prefix) {
$ip = $_SERVER['REMOTE_ADDR'];
$ip6_regex = '/^'.preg_quote(preg_replace('/::$/', '', $ip6_net)).':/';
$ip4_regex = '/^'.preg_quote($ip4_nat_prefix).'\./';
return (preg_match($ip6_regex, $ip) || preg_match($ip4_regex, $ip));
}
dispatch('/', function() {
exec('sudo iwconfig', $devs);
$wifi_device = moulinette_get('wifi_device');
@ -59,6 +67,7 @@ dispatch('/', function() {
$ip6_net = moulinette_get('ip6_net');
$ip6_net = ($ip6_net == 'none') ? '' : $ip6_net;
$ip4_nat_prefix = moulinette_get('ip4_nat_prefix');
set('wifi_ssid', moulinette_get('wifi_ssid'));
set('wifi_passphrase', moulinette_get('wifi_passphrase'));
@ -69,10 +78,11 @@ dispatch('/', function() {
set('ip6_net', $ip6_net);
set('ip6_dns0', moulinette_get('ip6_dns0'));
set('ip6_dns1', moulinette_get('ip6_dns1'));
set('ip4_nat_prefix', moulinette_get('ip4_nat_prefix'));
set('ip4_nat_prefix', $ip4_nat_prefix);
set('ip4_dns0', moulinette_get('ip4_dns0'));
set('ip4_dns1', moulinette_get('ip4_dns1'));
set('faststatus', service_faststatus() == 0);
set('is_connected_through_hotspot', is_connected_through_hotspot($ip6_net, $ip4_nat_prefix));
return render('settings.html.php');
});

View file

@ -43,3 +43,17 @@ div#github {
div#github a {
margin-left: 17px;
}
div#saveconfirmation {
display: none;
padding-right: 15px;
width: 60%;
margin: 0 auto;
}
div#saveconfirmation div#confirm {
background-color: #fff;
padding: 10px;
margin: 15px 0 0 0;
border: 1px solid #F5E79E;
}

View file

@ -36,6 +36,11 @@ $(document).ready(function() {
$('#form').submit();
});
$('#saveconfirm').click(function() {
$(this).hide();
$('#saveconfirmation').show();
});
$('#status .close').click(function() {
$(this).parent().hide();
});

View file

@ -154,7 +154,18 @@
<div class="form-group">
<div style="text-align: center">
<?php if($is_connected_through_hotspot): ?>
<div class="alert alert-dismissible alert-warning fade in" role="alert" id="saveconfirmation">
<strong><?= T_('Notice') ?>:</strong> <?= T_("You are currently connected through the wifi hotspot. Please, confirm the reloading, wait for the wifi disconnect/reconnect and go back here to check that everything is okay.") ?>
<div id="confirm">
<button type="submit" class="btn btn-default" data-toggle="tooltip" id="save" data-title="<?= T_('Reloading may take a few minutes. Be patient.') ?>"><?= T_('Confirm') ?></button> <img src="public/img/loading.gif" id="save-loading" alt="Loading..." />
</div>
</div>
<button type="button" class="btn btn-default" id="saveconfirm"><?= T_('Save and reload') ?></button>
<?php else: ?>
<button type="submit" class="btn btn-default" data-toggle="tooltip" id="save" data-title="<?= T_('Reloading may take a few minutes. Be patient.') ?>"><?= T_('Save and reload') ?></button> <img src="public/img/loading.gif" id="save-loading" alt="Loading..." />
<?php endif; ?>
</div>
</div>
</form>