Wednesday, July 05, 2006

The One-Minute Wireless Bridge

I am aware of the several fake access point projects available, like Rfakeap. Since one of the main purposes of my blog is to document how I configure applications for my personal future reference, I am listing the steps I performed to set up a wireless access point on FreeBSD.

The FreeBSD WAP laptop will receive its Internet connectivity via DHCP and a WEP-protected wireless network, from, say a conference. The laptop WAP will provide an encryption-free wireless connection to anyone who cares to connect.

I use two wireless NICs for this project.

First I connect the laptop to the local wireless network.

orr:/root# ifconfig wi0
wi0: flags=8802<BROADCAST,SIMPLEX,MULTICAST> mtu 1500
ether 00:02:2d:4c:ae:de
media: IEEE 802.11 Wireless Ethernet autoselect (none)
status: no carrier
ssid "" channel 1
stationname "FreeBSD WaveLAN/IEEE node"
authmode OPEN privacy OFF txpowmax 100
orr:/root# kldload wlan_wep
orr:/root# ifconfig wi0 ssid shaolin wepkey 0x[WEP key here] deftxkey 1 wepmode on up
orr:/root# dhclient wi0
DHCPDISCOVER on wi0 to 255.255.255.255 port 67 interval 3
DHCPOFFER from 192.168.2.1
DHCPREQUEST on wi0 to 255.255.255.255 port 67
DHCPACK from 192.168.2.1
bound to 192.168.2.102 -- renewal in 43200 seconds.
orr:/root# ifconfig wi0
wi0: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1500
inet6 fe80::202:2dff:fe4c:aede%wi0 prefixlen 64 scopeid 0x4
inet 192.168.2.102 netmask 0xffffff00 broadcast 192.168.2.255
ether 00:02:2d:4c:ae:de
media: IEEE 802.11 Wireless Ethernet autoselect (DS/2Mbps)
status: associated
ssid shaolin channel 6 bssid 00:13:10:65:2f:ad
stationname "FreeBSD WaveLAN/IEEE node"
authmode OPEN privacy MIXED deftxkey 1 wepkey 1:104-bit txpowmax 100
bintval 100
orr:/root# ping -c 1 www.google.com
PING www.l.google.com (64.233.161.104): 56 data bytes
64 bytes from 64.233.161.104: icmp_seq=0 ttl=229 time=61.857 ms

--- www.l.google.com ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max/stddev = 61.857/61.857/61.857/0.000 ms

The laptop wi0 wireless NIC has been assigned 192.168.2.102 via DHCP and it can reach the outside world.

Next I set up wi1 to be the wireless NIC for the WAP.

orr:/root# ifconfig wi1
wi1: flags=8802<BROADCAST,SIMPLEX,MULTICAST> mtu 1500
ether 00:04:e2:29:3b:ba
media: IEEE 802.11 Wireless Ethernet autoselect (none)
status: no carrier
ssid "" channel 1
stationname "FreeBSD WaveLAN/IEEE node"
authmode OPEN privacy OFF txpowmax 100
orr:/root# kldload bridge
orr:/root# sysctl net.link.ether.bridge.enable=1
net.link.ether.bridge.enable: 0 -> 1
orr:/root# sysctl net.link.ether.bridge.config="wi0 wi1"
net.link.ether.bridge.config: -> wi0 wi1
orr:/root# sysctl net.inet.ip.forwarding=1
net.inet.ip.forwarding: 0 -> 1
orr:/root# ifconfig wi1 ssid bejnet channel 11 media DS/11Mbps mediaopt hostap up stationname "BejNet AP"
orr:/root# ifconfig wi1 inet 10.10.10.1 netmask 255.255.255.0 up
orr:/root# ifconfig wi1
wi1: flags=8943 mtu 1500
inet6 fe80::204:e2ff:fe29:3bba%wi1 prefixlen 64 scopeid 0x5
inet 10.10.10.1 netmask 0xffffff00 broadcast 10.10.10.255
ether 00:04:e2:29:3b:ba
media: IEEE 802.11 Wireless Ethernet DS/11Mbps (DS/2Mbps )
status: associated
ssid bejnet channel 11 bssid 00:04:e2:29:3b:ba
stationname "BejNet AP"
authmode OPEN privacy OFF txpowmax 100 dtimperiod 1 bintval 100

At this point the WAP can transmit packets from wi1 to wi0 and vice-versa. However, it would be a good idea for the clients that associate with the WAP to get addresses via DHCP, preferably from a range not in use (e.g., not 192.168.2.0/24). This requires DHCP, which I set up in /etc/rc.conf:

dhcpd_enable="YES" # dhcpd enabled?
dhcpd_flags="-q" # command option(s)
dhcpd_conf="/usr/local/etc/dhcpd.conf" # configuration file
dhcpd_ifaces="wi1" # ethernet interface(s)

and /usr/local/etc/dhcpd.conf:

option domain-name "taosecurity.com";
option domain-name-servers 192.168.2.1;

default-lease-time 6000;
max-lease-time 72000;

ddns-update-style ad-hoc;
log-facility local7;

subnet 10.10.10.0 netmask 255.255.255.0 {
range 10.10.10.128 10.10.10.192;
option routers 10.10.10.1;
}

I'm being a little lazy here. I should replace the "legitimate" name server, 192.168.2.1, with 10.10.10.1 (my WAP), and configure a caching name server on my WAP. I'm going to avoid that step here, but I would probably do it elsewhere.

At this point you might think I am good to go. I have a rogue WAP on wi1 with IP 10.10.10.1 ready to serve IP addresses once I start dhcpd. The problem is I doubt the legitimate conference WAP knows how to reach my 10.10.10.0/24 network. Clients who associate with my laptop WAP will send traffic with source IPs like 10.10.10.192, but the conference WAP gateway at 192.168.2.1 will not know how to reach the 10.10.10.0/24 network.

The answer is to set up NAT on the laptop WAP.

orr:/root# kldload ipfw
orr:/root# kldload ipdivert
orr:/root# natd -dynamic -n wi0
orr:/root# ipfw add divert natd ip from any to any via wi0
00100 divert 8668 ip from any to any via wi0
orr:/root# ipfw add allow ip from any to any
00200 allow ip from any to any

Now the laptop WAP will NAT for connections on the wi1 network. Remember wi0 is closer to the "Internet" so the 192.168.2.0/24 network will see hosts on the 10.10.10.0/24 network coming from 192.168.2.102.

Last I start dhcpd.

orr:/root# /usr/local/etc/rc.d/isc-dhcpd.sh start
Starting dhcpd.
orr:/root# sockstat -4
USER COMMAND PID FD PROTO LOCAL ADDRESS FOREIGN ADDRESS
dhcpd dhcpd 1047 5 udp4 *:67 *:*
root natd 976 3 div4 *:8668 *:*
root sendmail 474 4 tcp4 127.0.0.1:25 *:*
root sshd 468 4 tcp4 *:22 *:*
root syslogd 320 7 udp4 *:514 *:*

That's it. Now I can watch the wi1 interface for traffic from anyone who associates with my laptop WAP. I check /var/db/dhcpd/dhcpd.leases and see the following:

lease 10.10.10.192 {
starts 3 2006/07/05 15:56:21;
ends 3 2006/07/05 17:36:21;
binding state active;
next binding state free;
hardware ethernet 00:13:02:4c:30:2d;
uid "\001\000\023\002L0-";
client-hostname "neely";
}

I got someone using host neely to associate with my BejNet laptop WAP. Now I watch for traffic.

orr:/root# tcpdump -n -i wi1 -s 1515
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on wi1, link-type EN10MB (Ethernet), capture size 1515 bytes
11:55:21.201914 arp who-has 10.10.10.1 tell 10.10.10.192
11:55:21.202170 arp who-has 10.10.10.1 tell 10.10.10.192
11:55:21.202372 arp reply 10.10.10.1 is-at 00:04:e2:29:3b:ba
11:55:21.204930 IP 10.10.10.192.1025 > 192.168.2.1.53: 9367+ A? www.google.com. (32)
11:55:21.484230 IP 192.168.2.1.53 > 10.10.10.192.1025:
9367 3/0/0 CNAME www.l.google.com., A 216.239.37.99, A 216.239.37.104 (84)
11:55:22.195205 IP 10.10.10.192.1025 > 192.168.2.1.53: 9367+ A? www.google.com. (32)
11:55:22.198575 IP 192.168.2.1.53 > 10.10.10.192.1025:
9367 2/0/0 A 216.239.37.99, A 216.239.37.104 (64)
11:55:22.203729 IP 10.10.10.192 > 216.239.37.99: ICMP echo request, id 1024, seq 2304, length 40
11:55:22.246182 IP 216.239.37.99 > 10.10.10.192: ICMP echo reply, id 1024, seq 2304, length 40

There we are. 10.10.10.192 is pinging Google. Here is the view from the other side of the NAT.

orr:/root# tcpdump -n -i wi0 -s 1515
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on wi0, link-type EN10MB (Ethernet), capture size 1515 bytes
11:55:21.202186 arp who-has 10.10.10.1 tell 10.10.10.192
11:55:21.205067 IP 192.168.2.102.1025 > 192.168.2.1.53: 9367+ A? www.google.com. (32)
11:55:21.484044 IP 192.168.2.1.53 > 192.168.2.102.1025:
9367 3/0/0 CNAME www.l.google.com., A 216.239.37.99, A 216.239.37.104 (84)
11:55:22.195388 IP 192.168.2.102.1025 > 192.168.2.1.53: 9367+ A? www.google.com. (32)
11:55:22.198491 IP 192.168.2.1.53 > 192.168.2.102.1025:
9367 2/0/0 A 216.239.37.99, A 216.239.37.104 (64)
11:55:22.203809 IP 192.168.2.102 > 216.239.37.99: ICMP echo request, id 1024, seq 2304, length 40
11:55:22.246099 IP 216.239.37.99 > 192.168.2.102: ICMP echo reply, id 1024, seq 2304, length 40

As far as the 192.168.2.0/24 network is concerned, 192.168.2.102 is making the request -- not 10.10.10.192.

That's it. Obviously this is exactly how to set up your own wireless access point for legitimate purposes. It's also how anyone could set up a WAP to watch traffic from anyone who decides to associate with my laptop WAP. This is the reason 802.11i and other systems are needed, although arbitrarily trusting wireless access points is more of a social problem than a technical problem.

Update: There appear to be some problems with comments, so I'll post additional thoughts here.

Chris asked about dispensing with DHCP and NAT.

I tried two approaches along those lines, but neither worked.

First I tried simply removing DHCP and NAT, but leaving wi0 with an IP address and assigning no IP address to wi1. In this scenario, I could see ARP traffic from an associated client for the DHCP server on the "conference" WAP (who has 192.168.2.1?) but the DHCP server on the conference WAP did not respond.

Next I tried doing nothing but setting up wi0 and wi1 as a pure bridge. wi0 associated with the conference WAP, and wi1 set up as an access point. Again, I could not get the DHCP server on the conference WAP to respond.

By the way, when I say "conference" I really mean the Linksys WRT54G WAP in my lab.

Remember that NAT is not strictly necessary if the conference WAP gateway knows how to reach the wi1 segment. This is not realistic, however, because it requires setting a static route for the wi1 segment on the conference WAP.

I also just renamed this article to be "The One Minute Wireless Bridge," since that is more in the spirit of what I'm doing -- providing one WAP to access another WAP.

6 comments:

Chris Byrd said...

Wouldn't it be possible to do the same thing, but use bridging between the wireless interfaces instead? This would allow you to still inspect/redirect/modify/drop traffic, with more transparency. It also might be simpler, as you wouldn't need to do anything with DHCP or NAT.

What do you think? Worth a try?

- Chris

Richard Bejtlich said...

Hi Chris,

You are right. I should have just stopped at the bridging phase. I will update this doc.

Richard Bejtlich said...

I can't seem to get the main DHCP server to respond to the DHCP REQUEST packets coming through the bridge. That is preventing me from eliminating the local DHCP server and NAT.

Richard Bejtlich said...

Test comment -- can anyone see this?

John Ward said...

Yes, I can see your comment...

Anonymous said...

Excellent post. Now if you can boost the signal, you can overpower the "conference" WAP...and you've just achieved a full wireless MITM attack. yay!

-LonerVamp