On this page
- How To Set Up A FreeBSD Wireless Access Point
How To Set Up A FreeBSD Wireless Access Point
This document will guide you on how to use a FreeBSD system as a wireless access point. This is intended to supplement the FreeBSD Handbook and not replace it.
Getting FreeBSD to act as a wireless access point involves the following steps:
- Make sure your installation includes hostapd and named (BIND)
- Recompile your kernel for pf support
- pf is not the only way to do this, but I strongly prefer pf to the ipfw/ipfilter and have written the How-To to use it
- Configure NAT (and any firewall rules)
- Install isc-dhcp3-server
- Configure daemons and start them
Hardware Requirements/Notes:
- One network card to connect to the upstream. This is the external network interface (ext_if). In this How-To it will be fxp0. Yours may differ.
- One wireless card to provide wireless services. I prefer Atheros-based cards, whatever FreeBSD supported card you have is fine, though (wifi_if). In this How-To it will be ath0. Yours may differ.
- Optionally, an additional wired network card (int_if) for wired LAN access (via crossover cable or a network switch/hub). Not necessary, but my system provides both wirless and wired LAN access. In this How-To it will be fxp1. yours may differ.
Downloadable sample configuration files are available at http://tun0.net/ascii/config/freebsd_access_point/.
Getting Started
Before we proceed, it's a good idea to connect the FreeBSD system you wish to make an access point to the Internet. Connecting to the Internet (or whatever upstream connection you have) is beyond the scope of this document. There is an entire chapter on Network Communication in the FreeBSD Handbook.
For the sake of simplicity, please execute all commands provided on this site as root. The majority of them will require root privileges anyway. To become root, type su, enter the root password and hit enter.
Check if you have BIND
BIND is usually distributed with FreeBSD, however, just to make sure BIND is present on your system, execute the following command:
which named
If that tells you named not found, then you will have to install BIND.
sudo pkg_add -r bind9
Check if you have hostapd
Check for hostapd using the which command:
which hostapd
The hostapd program is part of the base FreeBSD system. If it is not present, you may have a minimal system. You can use the FreeBSD installer to add more distribution sets or just update your system from sources and obtain it that way.
Check if you have kernel sources
You will need to build a custom kernel since the base kernel does not offer the OpenBSD Packet Filter (pf). This is a simple and relatively quick process and will be discussed later.
ls -l /usr/src/sys
If the above tells you No such file or directory or outputs no data, then you will need to obtain kernel sources. This is well explained in the Synchronizing Your Source section of the FreeBSD Handbook.
Recompile Your Kernel
The process of recompiling your kernel and including PF support is well documented in the FreeBSD Handbook. I shall summarize the process below.
Go to the kernel configuration directory and start your own kernel configuration based on the GENERIC (default, stock) kernel.
cd /usr/src/sys/`uname -m`/conf
cp GENERIC CUSTOM
You may edit the above how ever you wish as long as you know what you're doing. You can consult the /usr/src/sys/conf/NOTES file for explanations on any kernel option. Just make sure that you add the following lines for PF support. You may use vi, your favorite text editor, or just echo it into the file.
echo "device pf
device pflog
device pfsync" >> CUSTOM
Optionally, if you wish to take advantage of PF's traffic shaping abilities (ALTQ), I'd recommend adding the following lines to your custom kernel configuration:
options ALTQ options ALTQ_CBQ # Class Bases Queuing (CBQ) options ALTQ_RED # Random Early Detection (RED) options ALTQ_RIO # RED In/Out options ALTQ_HFSC # Hierarchical Packet Scheduler (HFSC) options ALTQ_PRIQ # Priority Queuing (PRIQ) options ALTQ_NOPCC # Required for SMP build
Now execute the following commands to build and install the new kernel.
cd /usr/src
make buildkernel KERNCONF=CUSTOM
make installkernel KERNCONF=CUSTOM
Finally, reboot so that you can use the new kernel.
shutdown -r now
Overview on Wireless Access Point Network
We will be setting up a system as follows:
- fxp0 - ext_if - external card that connects to cable/DSL modem, WAN, etc.
- fxp1 - lan_if - internal card that provides wired LAN access.
- ath0 - wifi_if - internal wireless card for wireless access point connections.
The network will be confgiured as follows:
- fxp0 - ext_if - DHCP configured from upstream (e.g. let cable modem provide an IP)
- fxp1 - lan_if - static IP, 192.168.0.1; wired subnet will be 192.168.0.0/24; clients on LAN configured via DHCP
- ath0 - wifi_if - static IP, 192.168.1.1; wireless subnet will be 192.168.1.0/24; clients on WLAN configured via DHCP
Configure the interfaces
Get an IP for the ext_if (the external interface)
dhclient fxp0
Set the IP on lan_if
ifconfig fxp1 inet 192.168.0.1 netmask 255.255.255.0
Make sure drivers are loaded for the wireless interface. For Atheros based cards you'll need the following single, one-line command:
for d in {if_ath,ath_rate,ath_hal}; do kldload $d; done
For any wireless card, including Atheros cards, make sure we have all the proper wireless modules loaded. The following is a long line, but it is a single, one-line command:
for d in {wlan_wep_load,wlan_tkip_load,wlan_ccmp_load,wlan_xauth_load,wlan_acl_load}; do kldload $d; done
Set the IP on wifi_if (ath0) using the single, one-line command:
ifconfig ath0 inet 192.168.1.1 netmask 255.255.255.0 ssid YOURSSID mediaopt hostap
Configure NAT (and any firewall rules)
First, let's set the system up to act as a router/gateway and enable PF. Perform the following commands as root.
sysctl -w net.inet.ip.forwarding=1
pfctl -e
Create a pf.conf for NAT and some basic firewall rules. Use vi or your favorite editor and add the following to the /etc/pf.conf file.
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # This configuration is set for use on a machine that is a router with # three (3) network cards: # ext_if - connects to the upstream link (cable/dsl modem, WAN, etc.) # wifi_if - wireless card for internal network # (if none present, remove all references to it in this file) # lan_if - wired card for internal network # (if none present, remove all references to it in this file) # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #------------------------------------------------------------------------ # macros #------------------------------------------------------------------------ logopt = "log" # interfaces ext_if = "fxp0" wifi_if = "ath0" lan_if = "fxp1" # publically accesible services (transport layer neutral) pubserv = "{ 22, 443 }" # internally accessible services (transport layer neutral) lanserv = "{ 22, 53, 67, 80, 443 }" # samba ports (transport layer neutral) samba_ports = "{ 137, 138, 139 }" # externally permitted inbound icmp types icmp_types = "echoreq" # internal network lan_net = "{ 192.168.0.0/24, 192.168.1.0/24 }" # hosts granted acces to samba (cifs/smb) shares smb_net = "{ 192.168.0.0/27, 192.168.1.0/27, 192.168.0.90, 192.168.1.90 }" # block these networks table{ 0.0.0.0/8, 10.0.0.0/8, 20.20.20.0/24, 127.0.0.0/8, \ 169.254.0.0/16, 172.16.0.0/12, 192.0.2.0/24, 192.168.0.0/16, \ 224.0.0.0/3, 255.255.255.255 } #------------------------------------------------------------------------ # options #------------------------------------------------------------------------ # config set block-policy return set loginterface $ext_if set skip on lo0 # scrub #scrub all reassemble tcp no-df #scrub in all fragment reassemble scrub out all random-id #------------------------------------------------------------------------ # redirection (and nat, too!) #------------------------------------------------------------------------ # network address translation nat on $ext_if from $lan_net to any -> ($ext_if) #------------------------------------------------------------------------ # firewall policy #------------------------------------------------------------------------ # restrictive default rules block all block return-rst in $logopt on $ext_if proto tcp all block return-icmp in $logopt on $ext_if proto udp all block in $logopt on $ext_if proto icmp all block out $logopt on $ext_if all # trust localhost pass in quick on lo0 all pass out quick on lo0 all # anti spoofing block drop in $logopt quick on $ext_if from to any block drop out $logopt quick on $ext_if from any to antispoof for { $lan_if, $wifi_if, $ext_if } # anti fake return-scans block return-rst out on $ext_if proto tcp all block return-rst in on $ext_if proto tcp all block return-icmp out on $ext_if proto udp all block return-icmp in on $ext_if proto udp all # toy with script kiddies scanning us block in $logopt quick proto tcp flags FUP/WEUAPRSF block in $logopt quick proto tcp flags WEUAPRSF/WEUAPRSF block in $logopt quick proto tcp flags SRAFU/WEUAPRSF block in $logopt quick proto tcp flags /WEUAPRSF block in $logopt quick proto tcp flags SR/SR block in $logopt quick proto tcp flags SF/SF # open firewall fully # warning: insecure. 'nuff said. #pass in quick all #pass out quick all # allow permitted icmp pass in inet proto icmp all icmp-type $icmp_types keep state # allow permitted services pass in on $ext_if inet proto tcp from any to any port $pubserv flags S/SA keep state pass in on {$lan_if $wifi_if} inet proto {tcp udp} from $lan_net to any port $lanserv keep state pass in on {$lan_if $wifi_if} inet proto {tcp udp} from $smb_net to any port $samba_ports keep state # permit access between LAN hosts pass in from $lan_net to $lan_net keep state pass out from $lan_net to $lan_net keep state # permit full outbound access # warning: potentially insecure. you may wish to lock down outbound access. pass out from any to any keep state
Load the above configuration with the following command:
pfctl -Fa -f /etc/pf.conf
Install and configure the ISC DHCP server
To dynamically assign IP addresses to clients on your LAN/WLAN, you'll need the ISC DHCP server.
pkg_add -r isc-dhcp3-server
Next edit it's configuration file, /usr/local/etc/dhcpd.conf:
### ### GLOBAL SETTINGS ### ddns-update-style none; always-broadcast on; default-lease-time 7200; max-lease-time 7200; authoritative; option domain-name-servers 192.168.1.1; option domain-name "localnet.localdomain"; option netbios-name-servers 192.168.1.1; ### ### WIRED LOCAL AREA NETWORK ### subnet 192.168.0.0 netmask 255.255.255.0 { # # NOTES: # (1) allocation of endings 100-199 by DHCP is # inteded for clients that are not specified # later in this file. # (2) allocation is done in increments of 10 # and this is done intentionally. # range 192.168.0.100 192.168.0.199; option broadcast-address 192.168.0.255; option subnet-mask 255.255.255.0; option routers 192.168.0.1; } ### ### WIRELESS NETWORK ### subnet 192.168.1.0 netmask 255.255.255.0 { # NOTE: See: wired->range.notes range 192.168.1.100 192.168.1.199; option broadcast-address 192.168.1.255; option subnet-mask 255.255.255.0; option routers 192.168.1.1; } ### ### ASSIGN SPECIFIC IP ADDRESSES TO SPECIFIC HOSTS BASED ON MAC ADDRESS ### (optional) ### ## host foo #host foo { # hardware ethernet XX:XX:XX:XX:XX:XX; # fixed-address 192.168.0.XYZ; #} ## host bar #host bar { # hardware ethernet XX:XX:XX:XX:XX:XX; # fixed-address 192.168.1.XYZ; #}
Configure hostapd
Edit /etc/hostapd.conf as follows:interface=ath0 driver=bsd logger_syslog=-1 logger_syslog_level=0 logger_stdout=-1 logger_stdout_level=0 debug=3 dump_file=/tmp/hostapd.dump ctrl_interface=/var/run/hostapd ctrl_interface_group=wheel #### IEEE 802.11 related config #### ssid=YOURSSID macaddr_acl=0 auth_algs=1 #### IEEE 802.1X related config #### ieee8021x=0 #### WPA/IEEE 802.11i config ##### wpa=1 wpa_passphrase=ENTER_YOUR_PASSPHRASE_HERE wpa_key_mgmt=WPA-PSK wpa_pairwise=CCMP TKIP
Make our settings permanant via rc.conf
We don't want to manually configure our interfaces or start our daemons manually each time, so we'll put it all into /etc/rc.conf:
### GENERAL SETTINGS gateway_enable="YES" hostname="wifiap" ### CONFIGURATION FOR EXTERNAL INTERFACE (UPSTREAM LINK) ### example: link to cable/dsl modem ifconfig_fxp0="DHCP" ### CONFIGURATION FOR INTERNAL WIRED NETWORK ifconfig_fxp1="inet 192.168.0.1 netmask 255.255.255.0" ### CONFIGURATION FOR INTERNAL WIRELESS NETWORK ifconfig_ath0="inet 192.168.1.1 netmask 255.255.255.0 ssid YOURSSID mediaopt hostap" ### CONFIGURATION FOR PACKET FILTER ### requires kernel recompile, see: ### http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/firewalls-pf.html pf_enable="YES" # Set to YES to enable packet filter (pf) pf_rules="/etc/pf.conf" # rules definition file for pf pf_program="/sbin/pfctl" # where the pfctl program lives pf_flags="" # additional flags for pfctl pflog_enable="YES" # Set to YES to enable packet filter logging pflog_logfile="/var/log/pflog" # where pflogd should store the logfile ### DAEMONS FOR LAN hostapd_enable="YES" # wireless services (clients use wpa_supplicant) named_enable="YES" # dns for clients dhcpd_enable="YES" # dhcp configure clients sshd_enable="YES" # so we can remotely access this box
We don't want to have to manually load kernel modules all the time either, so we'll put them into /boot/loader.conf:
wlan_wep_load="YES" wlan_tkip_load="YES" wlan_ccmp_load="YES" wlan_xauth_load="YES" wlan_acl_load="YES"
Start daemons
You can do this easily by rebooting:shutdown -r nowIf you're a true Unix zealot, however, and dislike rebooting unnecessarily, you can do the following:
/etc/rc.d/pflog start
/etc/rc.d/named start
/etc/rc.d/dhcpd start
/etc/rc.d/hostapd start
Done!
Congratulations! At this point, assuming you followed the directions and had no errors, you should have a functional wireless access point using WPA and a wired LAN that is connected to the upstream link.