DNS, The Masquerade
Scenario: a RaspberryPI primarily acting as access point, assigning IPs by DHCP and catching all DNS requests to redirect all HTTP traffic to himself, which may eventually switch to connect as a client to an existing wireless network (and delegating DHCP and DNS to another access point).
90% of this stuff may be easily achieved with nmcli
, the powerful and convenient command line interface for Network Manager.
nmcli c add type wifi ifname wifi-device con-name myconnection \
autoconnect yes ssid myconnection
nmcli connection modify myconnection \
802-11-wireless.mode ap 802-11-wireless.band bg ipv4.method shared
nmcli connection up myconnection
But I got stuck in a details. Using shared
method, nmcli
automatically provides a dnsmasq
instance properly configured as DHCP server on the same IP class and as DNS forwarding server, assuming that an upstream network connection is available to reach actual DNS. I've found no way to alter the behaviour of this ad-hoc dnsmasq
instance, and instrument it as a catch-all.
So I had to hack a little...
First of all, I've created a /etc/NetworkManager/dispatcher.d/90-update-dnsmasq.conf
script - to be executed at each change occurring at the networking status operated by NM - containing
#!/bin/sh
case "$2" in
"up")
ip=`ifconfig wlan0 | sed -En "s/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p"`
echo "address=/#/$ip" > /etc/dnsmasq.d/my-ip
service dnsmasq restart
esac
So, I configure dnsmasq
with a classic catch-all configuration.
But the dnsmasq
instance executed by NM ignores the configurations in /etc/dnsmasq.d/
, and cannot be replaced by killing it and starting again forcing the configurations due NM itself provides to automatically respawn it, causing a collision in the opening of TCP port 53.
Port TCP 53 is the solution to the dilemma.
I've modified the dnsmasq.conf file to make it listen at port 5353. This is ignored by the NM instance, but permits me to run another instance - through systemd
, and restarted by the above mentioned NM script - to manage the catch-all behaviour. At this point, it is obvious to setup a pair of iptables
rules to handle port redirection:
iptables -t nat -I PREROUTING -p tcp --dport 53 -j REDIRECT --to-port 5353
iptables -t nat -I PREROUTING -p udp --dport 53 -j REDIRECT --to-port 5353
In the end, I have:
- a Bash script that setups the network via
nmcli
, accordly to a file of mines - eventually, the instance of
dnsmasq
enabled by NM acting as DHCP server - another instance of
dnsmasq
, dynamically configured, acting as DNS server
Overkilling, but it works.