Firstly, only one non-base utility was used - dns/dnsmasq, a lightweight DHCP and DNS server. Everything else is in the base system. License purists should note that it's possible to do it with ISC BIND-related software, though more complicated.
Overall steps taken to create a functional FreeBSD AP with a wired connection are:
- Configure the network interface
- Configure firewall and NAT
- Configure dnsmasq
Configuring the wireless network interface
(It is assumed that the wired interface is configured somehow, possibly using dhclient)
FreeBSD 8 introduces a brand new way of handling wireless network interfaces. Contrasted to the old and familiar ways, now the network interfaces are not configured directly but through one or more virtual wireless network interfaces, WLANs. For example, instead of configuring ath0, a new virtual wireless interface called wlan0 must be created on top of ath0 and this new interface is configured. When I first heard about it, it seemed like an unnecessary new layer just standing in the way but after working with it I think it's really really cool since it allows fancy new features, like a single wireless NIC being both a client and an AP, or a client to more than one wireless networks (in both cases, only if supported by the hardware).
By default, I use wpa_supplicant (best thing since sliced bread for wireless connectivity configuration with myriad of options and protocols) for my regular wifi connectivity, and this takes my wlan0 device. For the AP configuration, I will use wlan1. First, the wlan1 device needs to be created / cloned, with some important options set:
ifconfig wlan1 create wlandev ath0 wlanmode hostap
The new wlan1 device will be created on top of ath0 and will be used as an AP (hostap). See the Handbook for description of wireless modes (and note syntax differences between versions of FreeBSD).
The device needs to be configured as usual:
ifconfig wlan1 ssid rakitovica2
ifconfig wlan1 inet 10.0.10.1/24
After the device is brought online (there is usually some reconfiguration delay), the new access point with the given ssid should be visible and associatable. In fact, if only static wireless connectivity is required this is everything needed for a simple setup to work. This configuration can be automated in the usual way in /etc/rc.conf.
I have used "OPEN" wireless security, without encryptions or passwords. WEP, WPA and WPA2 can be configured on this layer if needed. Again, read the Handbook for details.
Firewall and NAT configuration
I like to use ipfw because of its clean syntax (which includes lack of sygils in the syntax; see Python, another of my favorites) and a rich and consistent feature set. I used ipfw for NAT and some simple firewall rules:
ipfw add 1000 deny ip from any to 192.168.1.0/24 in via wlan1
ipfw nat 1 config ip 192.168.1.190 reset
ipfw add 2000 nat 1 all from any to any
ipfw add 3000 allow ip from any to any
The first line cretes rule 1000 which will ban IP traffic incoming from wlan1 going to the protected network. The second line creates a NAT configuration (ID 1) which will masquerade traffic as the IP address 192.168.1.190, which was configured (by DHCP) on the wired network interface. The third line pases all traffic through the NAT configuration 1 and the fourth simply allows all further traffic. This is a very simple NAT configuration - much more complex variations are possible, including various port and network redirection forms.
IPFW is implemented as a kernel module named ipfw.ko and is usually enabled in rc.conf. The NAT feature of IPFW is implemented in the kernel module ipfw_nat.ko. Both need to be loaded for this configuration to work.
DNSMASQ is a simple DHCP server and DNS proxy. After it's installed from ports, an example configuration file in /usr/local/etc can be copied to the active configuration file dnsmasq.conf. There are few lines that need to be configured here:
The first line configures dnsmasq to only listen on wlan1. The second establishes the default domain name (for convenience only) and the third configures a DHCP range. Other defaults will be picked up from the currently running system (including true, non-masquaraded resolv.conf and routes).
Full logging in dnsmasq.conf can be enabled by using these lines:
How does it work
Though personally I think there's some ambiguity in the order of processing between NAT and the DHCP server (i.e. - does DNSMASQ recive a NATted DHCPREQUEST packet?), the setup seems to work. In any case, DNSMASQ is standalone and simply serves IP addresses to the clients on wlan1. IPFW then does NATting of all traffic received (if needed).
The end result is a simple AP, offering DHCP service and performing NAT to allow the clients Internet access, with some simple firewalling.
All together, about 9 lines of commands or configuration need to be entered.
All these steps can be automated natively with FreeBSD standard configuration facilities. NIC configuration (ifconfig) can be recorded in /etc/rc.conf as usual; ipfw firewall settings can be written to a file and called from /etc/rc.conf with the firewall_type configuration variable and DNSMASQ is if course controlled by its own config file. In this way, a machine can be made to boot with ra eady-made AP configuration.