home January 01, 2017

FreeBSD Wireless Access Point


How to setup a wireless access point (WAP) on FreeBSD 10

When our trusty Linksys WRT54GL Wi-Fi Wireless-G Broadband Router running the dd-wrt firmware died after ten(10) years it was finally time to construct our own wireless access point. FreeBSD is our chosen OS because of FreeBSD's excellent network stack, network monitoring tools and the Pf firewall. Configuring a FreeBSD wireless access point (WAP) is not difficult once you find compatible hardware because all the software you will need is included in the FreeBSD distribution.

The goal of the project is to allow all wireless clients, like smart phones and tablets, to connect to our Wireless Access Point (WAP) using the uncongested 5 GHz wireless band on enterprise class channel 165, authenticate using a single pass phrase for all users and encrypt bulk data with AES encryption. Clients should expect to receive at least 54 Mbps (6.75 MB/s) of wireless throughput.

Hardware

The first, and most frustrating step when setting up an access point is identifying compatible hardware. A wireless chipset must support wireless "infrastructure mode" to allow clients to authenticate to the wireless card. The hardware needs to be supported by a driver available in FreeBSD and the chipset must support an 802.11 protocol compatible with the other wireless clients which connect to the access point. Our group already have FreeBSD firewalls setup and we wanted to use the same servers for the WiFI access point. Also, in order to transmit at high wattage a PCI card would be a better solution compared a smaller five(5) volt USB wireless stick.

The most recommended wireless chipset compatible with FreeBSD is made by Qualcomm Atheros which uses the FreeBSD ath0 driver; ATH9k in Linux. The man page for the ath0 driver specifies that the Atheros AR9380 chip supports "infrastructure mode" and 802.11a/b/g/n at 2.4GHz or 5GHz.

Our access point uses the following hardware listed in the window below and costs as little as $30 US. The wireless card has a single radio and will support one frequency band at a time. This means you can run a 2.4 GHz or a 5 GHz wireless network, but not both frequencies at the same time. If you want to support both frequencies at the same time purchase two(2) wireless cards.

FreeBSD 10 Drivers: due to a limitation in the ath0 driver for FreeBSD 10 we are restricted to 802.11g for 2.4 GHz networks and 802.11a for 5 GHz networks. The result is clients are limited to 54 Mbps of bandwidth. The good news is the driver in FreeBSD 11 will support 802.11n with the same TP-LINK card allowing clients to use multiple-input multiple-output (MIMO) to reach the full 450 Mbps speeds this card can support. FYI: the developers of Pfsense v2.2 imported the newest ath0 driver into their distribution if you wanted to use this same card with 802.11n now.

Antennas: the three(3) antennas which are included with the wireless card are short, omnidirectional antennas which stick out the back of the computer case. The rear of a computer is not an optimal location for radio transmitters because the computer case is made of rolled steel and metal blocks wireless radio signals. The two optional antennas listed in the window below provide a four(4) foot cable leading to the external antenna mount allowing one to place the antenna in a higher location away from the server case. During testing we found the default 2 dBi antennas can support clients at thirty feet or so. The optional omnidirectional antenna increased that range to seventy feet and the directional antenna jumped the distance to well over one hundred feet through multiple residential walls. We were able to combine up to three(3) of these optional antennas on a single wireless card to significantly increase the coverage area.

# Wireless PCIe Card

Product Model       : TP-LINK TL-WDN4800
Wireless Chipset    : Atheros AR9380
Wireless Technology : 802.11a/b/g/n 3T3R MIMO @ 2.4 GHz or 5 GHz
Wireless Modes      : Ad-Hoc and Infrastructure mode (hostap)
Transmit Power (US) : 20dBm EIRP,  100 mW , 2.4 GHz , channel   1 - 13
                      23dBm EIRP,  200 mW ,   5 GHz , channel  23 - 36
                      30dBm EIRP, 1000 mW ,   5 GHz , channel 149 - 165
Connector Type      : RP-SMA Female
Number of antennas  : Three(3) , 2 dBi omnidirectional


# Omnidirectional Antenna, optional

Product Model       : TP-LINK TL-ANT2405C
Wireless Technology : 2.4 GHz or 5 GHz
Antenna Gain        : 5 dBi , 360 degrees , horizontal plane only
Cable Length        : 1.3m / 4ft , 100cm low loss CFD-200 cable 
Connector Type      : RP-SMA Male


# Directional Antenna, optional

Product Model       : TP-LINK TL-ANT2409A
Wireless Technology : 2.4 GHz or 5 GHz
Antenna Gain        : 9 dBi , 60 degree cone from the front only
Cable Length        : 1.3m / 4ft , 100cm low loss CFD-200 cable 
Connector Type      : RP-SMA Male

Install the card, initialize the wlan0 interface

FreeBSD will initialize the wireless card's ath0 drivers on boot and the ath0 device will show up using "ifconfig". The ath0 interface now needs to be bound to a wireless LAN interface called wlan0 in host access point mode, hostap. Add the following configuration to /etc/rc.conf to make the wlan0 interface bound to ath0, initialize hostap mode on the card and set the wlan0 interface to the private ip address 10.0.100.1. On this network all wireless devices will have an ip address on the 10.0.100.0/24 subnet and use 10.0.100.1 as their default gateway. Reboot to enable the settings.

user@calomel#  vi /etc/rc.conf

# wireless
wlans_ath0="wlan0"
create_args_wlan0="wlanmode hostap"
hostapd_enable="YES"
ifconfig_wlan0="inet 10.0.100.1 netmask 255.255.255.0"

Verify the hardware capabilities

Once the drivers are loaded we can verify the hardware supports "infrastructure mode" which means the card can be configured as an access point. Using the following ifconfig command list out the capabilities of the wlan0 interface. Take a look at the first line for the string "HOSTAP" which we have highlighted in bold font. HOSTAP is host access point mode which is another name for "infrastructure mode". Also note the second line includes AES_CCM which is the 128 bit Advanced Encryption Standard (AES) bulk data encryption our access point will use.

user@calomel#  ifconfig wlan0 list caps

drivercaps=4f85ed01<STA,IBSS,HOSTAP,AHDEMO,TXPMGT,SHSLOT,SHPREAMBLE,MONITOR,MBSS,WPA1,WPA2,BURST,WME,WDS,TXFRAG>
cryptocaps=1f<WEP,TKIP,AES,AES_CCM,TKIPMIC>
htcaps=701ee<CHWIDTH40,SHORTGI20,SHORTGI40,TXSTBC>

The Host Access Point Daemon

A wireless access point consists of three(3) parts: the native hardware interface ath0, the wireless LAN interface wlan0 configured as HOSTAP and the hostapd daemon to control how the access point behaves.

The hostapd daemon is the program which will control all aspects of the wireless card including: authentication, encryption, channel section, transmit power modes and modulation standards.

The hostapd daemon is installed by default on FreeBSD. To configure hostapd create a new file called "/etc/hostapd.conf" and place the following configuration into the file. Take a look at the comments we included in the configuration for details. The hostapd server can be manually started using "service hostapd start" and started at boot by adding hostapd_enable="YES" to /etc/rc.conf .

user@calomel#  vi /etc/hostapd.conf


# The name of our access point. An SSID (Service Set IDentifier) is the wifi
# name broadcast to all 802.11 wireless local area network (WLAN) clients.
# Spaces and new line "\n" characters are allowed and the string is case
# sensitive.
ssid=the promised lan

# The security password or pass phrase. The correct WPA pass phrase is required
# by all Wifi clients before being allowed to connect to the Access point (AP).
# Long strings have greater entropy compared to short, complicated passwords.
# Spaces are allowed and the string is case sensitive.
wpa_passphrase=drop it like its hotspot

# The WiFi channel. Specify the channel number and the driver will set the
# proper frequency, 2.4GHz or 5GHZ, and the allowed transmit power (txpower).
# The list of available channels supported by the hardware and driver can be
# queried using, "ifconfig -v wlan0 list channel" . Default channels in the US
# are: 1, 2, 3, 4  5, 6, 7, 8, 9, 10, 11 for 2.4GHz networks and 36, 40, 44, 48
# for 20dBm low power 5GHz and 149, 153, 157, 161, 165 for 30dBm high power
# 5GHz. Recommended channels are 1, 6, or 11 for 2.4GHz networks and 149,
# 153, 157, 161 or 165 for 5GHz networks.
channel=165

# The wireless LAN interface the ath0 card was created with. wlan0 is the default.
interface=wlan0

# Set the modulation standard, a/b/g . When setting the hw_mode to "g" the
# interface will support 802.11g at 2.4GHz and 802.11a at 5GHz. This is a
# limitation of the ath0 driver in FreeBSD 10. In FreeBSD 11 the driver will
# be updated and 802.11n will become available by enabling ieee80211n . 802.11n
# supports ht/40+ , both 20 MHz and 40 MHz wide multiple-input multiple-output
# (MIMO) streams increasing throughput to 450 Mbps.
hw_mode=g
#ieee80211n=1
wmm_enabled=1

# Authorization type. The following requires the client to authenticate using
# WPA2 / 802.11i mode using a single password for all users specified above
# using "wpa_passphrase". CCMP requires the connection to use AES encryption.
auth_algs=3
wpa=2
wpa_key_mgmt=WPA-PSK
wpa_pairwise=CCMP
rsn_pairwise=CCMP

# Wifi thresholds defined to govern the size of packets and the number of
# beacons as specified by our access point (AP). We choose to increase the
# beacon interval from 100ms to 1000ms to reduce the beacon traffic overhead. A
# higher beacon interval increases the throughput of the access point by
# only two(2) to three(3) megabits at most.
beacon_int=1000
dtim_period=2
max_num_sta=255
rts_threshold=2347
fragm_threshold=2346

# Log all "informational messages" and above to syslog.
logger_syslog=-1
logger_syslog_level=2

# System files 
dump_file=/tmp/hostapd.dump
ctrl_interface=/var/run/hostapd
ctrl_interface_group=0

Verify the access point is up

When the hardware is configured and the hostapd daemon is running the access point is online. Use the following ifconfig line to look at the details of the wlan0 interface, You should recognize the SSID name and the channel number from the hostapd.conf file.

user@calomel#  ifconfig

ath0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 2290
        ether 60:e3:27:11:22:33
        nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>
        media: IEEE 802.11 Wireless Ethernet autoselect mode 11a <hostap>
        status: running

wlan0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
        ether 60:e3:27:11:22:33
        inet 10.0.100.1 netmask 0xffffff00 broadcast 10.0.100.255 
        nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
        media: IEEE 802.11 Wireless Ethernet autoselect mode 11a <hostap>
        status: running
        ssid the promised lan channel 165 (5825 MHz 11a) bssid 60:e3:27:11:22:33
        regdomain 33 indoor ecm authmode WPA2/802.11i privacy MIXED
        deftxkey 3 AES-CCM 2:128-bit AES-CCM 3:128-bit txpower 30 mcastrate 6
        mgmtrate 6 scanvalid 60 wme burst dtimperiod 1 -dfs

Mobile devices should see the SSID

Wireless devices should now be able to see the SSID of the access point. You should be able to authenticate to the access point as well, but your packets will not be passed through the machine until the firewall allows traffic to pass from the wireless interface to the wired interface.

Check out our FreeBSD Network Performance and Tuning tutorial for tips on configuring a fast and secure FreeBSD server.

FreeBSD Pf packet forwarding /etc/rc.conf

Clients authenticated to the wireless access point will have an ip on the same subnet as the wlan0 interface. The Pf firewall can be used to pass wireless client packets to another interface on the wired network. Enable FreeBSD's gateway mode to allow packets to be forwarded from one network interface to another. Then enable Pf so rules in /etc/pf.conf will be loaded on boot.

user@calomel#  vi /etc/rc.conf


# allow packets to be passed from one network interface to another
gateway_enable="YES"            # Enable as LAN gateway

## PF firewall
pf_enable="YES"                 # Enable PF (load module if required)
pf_rules="/etc/pf.conf"         # rules definition file for pf
pf_flags=""                     # additional flags for pfctl start up
pflog_enable="YES"              # start pflogd(8)
pflog_logfile="/var/log/pflog"  # where pflogd should store the logfile
pflog_flags=""                  # additional flags for pflogd start up

Basic /etc/pf.conf for wireless testing

The following is a minimal Pf firewall configuration to allow all packets though the wireless device to our wired LAN card. The wired network card in this case is an Intel igb0 interface on the $lan_if variable and the wlan0 interface on the $wifi_if variable. For more information about Pf check our Pf Firewall Tutorial.

user@calomel#  vi /etc/pf.conf


# interfaces
lan_if="igb0"
wifi_if="wlan0"

# options
set block-policy return

# pass on lo
set skip on lo

# NAT
nat on $lan_if from $wifi_if:network to !($lan_if) -> ($lan_if)

# default, deny everything
block in log all

# out is ok
pass out log quick

# pass inet4 and inet6 traffic in on wifi and lan
pass in log on $wifi_if inet
pass in log on $wifi_if inet6
pass in log on $lan_if inet
pass in log on $lan_if inet6

# icmp all good
pass out log inet proto icmp from any to any keep state
pass in log quick inet proto icmp from any to any keep state

Wireless client ip addresses

Clients need an ip address once they authenticate to the wireless network. There are two(2) options: manually give out an ip addresses or use DHCP. We run a small private network which rarely adds new devices. We prefer to assign static ip addresses to our clients. Static ip addressed clients join the network faster since they do not have to wait to be assigned an allowed ip address on the subnet. DHCP is easier if you have many clients entering and leaving the network.

Static IPs can be assigned to a wireless client by selecting the SSID name of the network, in our case the SSID is "the promised lan". Depending on your client configuration, provide the password and choose to setup the ip addresses manually instead of DHCP. To add a client to our example wireless network manually we would use the following values. Once a client is configure the settings will be saved and the client will automatically join the wireless network every time they are in range of the access point.

SSID      : the promised lan
password  : drop it like its hotspot

ip address:  10.0.100.10
subnet    :  255.255.255.0
gateway   :  10.0.100.1
DNS       :  8.8.8.8

DHCP IPs require the use of the DHCPd daemon listening on the ip address of the wlan0 interface, in this case the wlan0 ip address in 10.0.100.1 . Install ISC's dhcpd server and configure /etc/rc.conf and /usr/local/etc/dhcpd.conf . Make sure to start the dhcpd daemon.

user@calomel#  vi /etc/rc.conf 

dhcpd_enable="YES"
dhcpd_ifaces="wlan0"
user@calomel#  pkg install isc-dhcp41-server

user@calomel#  vi /usr/local/etc/dhcpd.conf

### Lease Times
default-lease-time 86400;
max-lease-time 86400;

### Options
authoritative;
get-lease-hostnames true;
option broadcast-address 10.0.100.255;
option routers 10.0.100.1;
option subnet-mask 255.255.255.0;

### DHCP Address Bank of 100 ip addresses
subnet 10.0.100.0 netmask 255.255.255.0
  {
  range 10.0.100.100 10.0.100.200;
  }


user@calomel#  service isc-dhcpd start 

Wireless Access Point Complete

You should now be able to see your SSID on any wireless client. Choose the SSID and the client will authenticate with the pass phrase to join the network passing packets through the FreeBSD Pf firewall.

Questions?

Which wireless channel should I choose ?

The short answer is channel 1, 6 or 11 for 2.4 GHz networks and channels 149, 153, 157, 161 or 165 for 5 GHz networks.

In the 2.4 GHz band, 1, 6 and 11 are the only non-overlapping channels. Each channel on the 2.4 GHz spectrum is 20 MHz wide. The channel centers are separated by 5 MHz, and the entire spectrum is 100 MHz wide in total. This means that the 11 channels have to squeeze into only 100 MHz and most channels overlap. Overlapping signals cause distortion in neighboring channels which leads to lower speeds for everyone.

For the 5GHz band none of the 20 MHz channels overlap. What is important to note is that the lower channels will limit their transmit wattage to 100 milliwatts due to the "old rules" of US FCC regulations. The upper channels 149 though 165 are allowed to transmit at 1000 milliwatts resulting in a stronger signal and greater range. We suggest using channel 165 at 5 GHz because channel 165 is not normally included in residential home wireless routers from Verizon FIOS or Comcast. Channel 165 is considered enterprise class and normally never used in a home network, but all 5 GHz devices in the US will connect to an AP using channel 165.

Can I turn the WiFi off and on at certain times ?

Yes, setup a cron job to stop and start the hostapd daemon. Hostapd controls all authentication and access to the wireless device as well as turning on and off the radios. You do not have to take down the ath0 or wlan0 interfaces. The following cron job will turn the wireless access point off at 11pm at night and back on at 6am in the morning. Clients will automatically connect to the access point when the radio starts transmitting at 6am.

root@calomel#  crontab -e

#minute (0-59)
#|   hour (0-23)
#|   |    day of the month (1-31)
#|   |    |   month of the year (1-12)
#|   |    |   |   day of the week (0-6 with 0=Sun)
#|   |    |   |   |   commands
#|   |    |   |   |   |
#
#
00   23   *   *   *   service hostapd stop
00   06   *   *   *   service hostapd start

Does running the radio at 30 dBm generate excess heat ?

No, the card does not get hot. In the US the FCC allows the transmit power of 30 dBm (txpower 30) or 1000 mW for the upper 5 GHz channels. Use "ifconfig wlan0" to check your transmit power rating, "txpower". The ath0 wireless card is cool to the touch after running for days with an average of ten(10) wireless clients.

How can I edit the transmit power by channel and country code ?

The regulatory domain database is in an XML file located in /etc/regdomain.xml and used by ifconfig(8) to view and manipulate regulatory domain settings.