FreeBSD:Building a Wireless Access Point

From Zoelife4U Wiki
Jump to: navigation, search

Contents

Using FreeBSD as a Wireless Access Point / Wireless Router

This document will guide you on how to use a FreeBSD system as a wireless access point (wifi router). This is intended to suppliement 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  pfw/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 wireless 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.

If you're aiming for only a wireless LAN, you can omit all references to fxp1 and lan_if. In configuration files simply delete $lan_if from all files. Conversely, for wired only setups, remove all references to $wifi_if and ath0.

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 now If you're a true Unix zealot, however, and dislike rebooting unnecessarily, you can do the following:

	/etc/rc.d/pflog restart
	/etc/rc.d/named restart
	/etc/rc.d/dhcpd restart
	/etc/rc.d/hostapd restart

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.

Personal tools
Online Users
Zoelife4U: