Wireless AP with udhcpd and NAT
Setting up a wireless AP with udhcpd and NAT
(baseed largley on the raspberry pi wireless router howto)
hostapd provides the AP. udhcpd is the dhcp server.
If you want to connect clients to the internet, you need to provide some way of redirecting traffic from the AP to the rest of the internet. There are two main possibilities:
- setting up a bridge
- using NAT (network address translation).
If you use a bridge and get your IP via DHCP, you may have a hard time configuring it so that the bridge gets an ip without screwing up your local internet connection. This guide only covers NAT; see Bridge for more on the alternative.
You need to write a configuration file; Alpine ships with a sample one in /etc/hostapd/hostapd.conf, but it didn't work for me (possibly because I used a pre wireless-N card, supported by ath5k?).
Here's a sample one based on something that did work for me (I've changed ssid & wpa_passphrase):
ctrl_interface=/var/run/hostapd ctrl_interface_group=0 interface=wlan0 driver=nl80211 logger_syslog=-1 logger_syslog_level=2 logger_stdout=-1 logger_stdout_level=2 ssid=alpine-test hw_mode=g channel=6 max_num_sta=32 rts_threshold=2347 fragm_threshold=2346 macaddr_acl=0 auth_algs=3 ignore_broadcast_ssid=0 wpa=2 wpa_passphrase=supertopsecret wpa_key_mgmt=WPA-PSK WPA-PSK-SHA256 wpa_pairwise=TKIP CCMP
Change "interface" to match your wireless interface. Change "ssid" and "wpa_passphrase" to suit your desires. Set "wpa" to 3 if you want plain wpa and wpa2. or 1 for plain WPA1 only.
The example in the package uses wpa_psk_file (needed for WPS) instead of a static passphrase; this does not enable WPS.
You may want to change the channel to avoid collision with other local APs. Unfortunately, the automatic channnel selection (channel=0) is *not* currently enabled at compile time, so we can't use it; scan for channels
in use with
or equivalent before setup.
max_num_sta is a limit to the number of clients connecting to your AP. Set it higher than you think you could have, but not much higher.
If you don't put this in /etc/hostapd/hostapd.conf, you will need to change the CONFIGS line in /etc/conf.d/hostapd to point at it. I prefer doing that, so that the default is available for reference.
Edit /etc/udhcpd.conf. The default is very well-commented, but not perfectly ready to use. Here's a skeleton, loosely based on mine:
start 192.168.2.2 end 192.168.2.254 max_leases 64 interface wlan0 static_lease 00:1b:de:ad:be:ef 192.168.2.100 opt dns 192.168.0.1 18.104.22.168 opt subnet 255.255.255.0 opt router 192.168.2.1 opt lease 864000
Note the following:
- max_leases should be set to at least as many clients as you might have in
the lifetime of a lease; if you have any clients connecting via bridges, note that the bridge itself gets a dhcp address.
- interface is the interface clients will be connecting to (wlan0 or your
wireless interface in our example)
- router should be the static IP address you give to your wireless interface.
- start and end should be within the same subnet as the IP you configure
wlan0 with, but the IP for wlan0 should be outside the range. (For example: 192.168.2.1 and 192.168.2.255 are both suitable for the router IP in this example.)
- set the dns option to point to any nameservers you want; you can repeat it,
but there's a maximum of 3 nameservers.
- static_lease takes two arguments: a MAC address designating a specific
network adaptor, and the IP address that should be assigned to it. It can be repeated multiple times, to assign different IPs to different users. This comes in handy for printers, if you can trust those who connect to the network to not do MAC spoofing.
I used raw iptables, configuring it thus:
- this saves the state somewhere that the service can restore it from
service iptables save
and try connecting from another computer.
Make changes permanent
Now, the odd parts: iptables tries to set net.ipv4.ip_forward to 1 when it's started, but in my experience, this cannot be relied upon. You do *not* want to enable the "iptables" service; it starts before networking, and may result in your wireless interface not getting configured. (Apparently, ifup thinks that wlan0 is up and skips it. This was not something I expected, but it's the only explanation I have for how things worked...)
Rather, modify /etc/network/interfaces, commenting out any configuration for your wireless interface. Then add this:
auto wlan0 iface wlan0 inet static address 192.168.2.1 netmask 255.255.255.0 up /etc/init.d/iptables start up sysctl net.ipv4.ip_forward=1 down /etc/init.d/iptables stop
(It would be possible to set everything up so that hostapd and udhcpd get started and stopped from the wlan0 stanza; I didn't bother doing that.)
(See Setting_up_a_ssh-server for alternatives and more information) Add dropbear SSH server, configure it to run on only the wireless interface:
edit /etc/conf.d/dropbear to add
(assuming that the wireless interface has the IP 192.168.2.1 and you want SSH on port 22). This is optional, but if you're using a wireless router it helps to be able to administer it, and listening on all addresses is rather risky.
Things this doesn't cover but it would be nice to
- Some way to get more entropy (see Entropy_and_randomness)
- DNS server, publishing device names (TinyDNS_Format looks most useful)
- use awall instead of raw iptables (and/or switch to nftables)
- Setup-acf to manage the router
This would require:
- acf-core, acf-alpine-conf, acf-apk-tools
- acf-iptables, or acf-awall + rewrite
- acf-ssh + switch to openssh, or new acf-dropbear
- acf-dhcp + switch to dhcp, or new acf-udhcpd
- new acf-hostapd (probably hardest part!)
- acf-tinydns after adding tinydns