Press "Enter" to skip to content

binat on OpenBSD’s pf Confuses Me

UPDATED: This is fixed. See the bottom of the post.

With the move to Wide Open West for data service at home I now have up to three IPs available, all assigned via DHCP. In order to best use them and work around the Xbox Live problems I was having I wanted to do the following:

– Assign one IP to one interface, and NAT everything through it, like normal.
– Assign a second IP to a second interface, and use binat to have my Xbox 360 to basically have its own public connection. (Sort of like being in the DMZ on a Linksys box.)
– Leave the third IP alone for times when I want a non-firewalled connection.

While I have this set up, it doesn’t seem to be working. Here’s my current configuration. If anyone can tell me what I’m doing wrong or offer suggestions, please do so:

– WebStar cable modem plugged into a switch.
– Two interfaces on the firewall fxp0 and fxp1 plugged into the switch.
– DHCP on fxp0 and fxp1 resulting in the following:

fxp0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
        lladdr 00:02:a5:da:e4:00
        groups: egress
        media: Ethernet autoselect (100baseTX full-duplex)
        status: active
        inet6 fe80::202:a5ff:feda:e400%fxp0 prefixlen 64 scopeid 0x1
        inet 74.199.15.37 netmask 0xfffff000 broadcast 74.199.15.255
fxp1: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
        lladdr 00:02:a5:da:e4:01
        media: Ethernet autoselect (100baseTX full-duplex)
        status: active
        inet6 fe80::202:a5ff:feda:e401%fxp1 prefixlen 64 scopeid 0x2
        inet 74.199.15.89 netmask 0xfffff000 broadcast 74.199.15.255

trashwall# route -n show
Routing tables

Internet:
Destination        Gateway            Flags   Refs      Use   Mtu  Prio Iface
default            74.199.0.1         UGS        7  3931950     -    48 fxp0
74.199.0/20        link#1             UC         1        0     -    48 fxp0
74.199.0.1         00:01:5c:31:83:42  UHLc       1        0     -    48 fxp0
74.199.15.37       127.0.0.1          UGHS       0        0 33204    48 lo0
74.199.15.89       127.0.0.1          UGHS       0        0 33204    48 lo0
127/8              127.0.0.1          UGRS       0        0 33204    48 lo0
127.0.0.1          127.0.0.1          UH         4    15344 33204    48 lo0
192.168.0/24       link#3             UC         5        0     -    48 fxp2
192.168.0.2        00:16:cb:c5:16:2f  UHLc       0       51     -    48 fxp2
192.168.0.5        00:00:aa:a6:89:e0  UHLc       0        1     -    48 fxp2
192.168.0.6        00:11:d9:16:54:43  UHLc       0    63515     -    48 fxp2
192.168.0.10       00:17:f2:09:81:c6  UHLc       2   351684     -    48 fxp2
192.168.0.25       link#3             UHLc       1    52623     -    48 fxp2
192.168.1/24       link#9             UC         0        0     -    48 wi0
224/4              127.0.0.1          URS        0        0 33204    48 lo0

(IPv6 Stuff Omitted)

I’ve then got set up with the following very basic binat rule and nothing else. With this set I can ping both interfaces (fxp0: 74.199.15.37, fxp1: 74.199.15.89) from the outside:

trashwall# cat /etc/pf.conf
binat on fxp1 from 192.168.0.10 to any -> fxp1

When I try to ping 208.83.71.138 (nuxx.net) from 192.168.0.10 (internal machine on the binat line above) I see the following on fxp0, the external interface on the firewall:

trashwall# tcpdump -ni fxp0 host 208.83.71.138
tcpdump: listening on fxp0, link-type EN10MB

09:30:23.036562 192.168.0.10 > 208.83.71.138: icmp: echo request
09:30:24.036532 192.168.0.10 > 208.83.71.138: icmp: echo request
09:30:25.036758 192.168.0.10 > 208.83.71.138: icmp: echo request
09:30:26.036702 192.168.0.10 > 208.83.71.138: icmp: echo request
^C
70 packets received by filter
0 packets dropped by kernel
trashwall#

I shouldn’t be seeing a private, internal address going out of the firewall. My understanding of binat, from both the PF: Network Address Translation article and the pf.conf man page say that it should be doing bidirectional mapping. To quote:

A bidirectional mapping can be established by using the binat rule. A binat rule establishes a one to one mapping between an internal IP address and an external address. This can be useful, for example, to provide a web server on the internal network with its own external IP address. Connections from the Internet to the external address will be translated to the internal address and connections from the web server (such as DNS requests) will be translated to the external address. TCP and UDP ports are never modified with binat rules as they are with nat rules.

I have also tried changing the binat line to be binat on fxp1 from 192.168.0.10 to any -> 74.199.15.89 which is how the example is given (as opposed to the interface name, as in the man page) but that doesn’t make a difference.

There’s one other thing to note, which I’m not sure is related or not. If I try to ping 208.83.71.138 with the outgoing interface set to 74.199.15.89 (fxp1) I see the pings go out with the right source address (74.199.15.89) but via the wrong interface (fxp0):

trashwall# ping -I 74.199.15.89 208.83.71.138
PING 208.83.71.138 (208.83.71.138): 56 data bytes
--- 208.83.71.138 ping statistics ---
6 packets transmitted, 0 packets received, 100.0% packet loss
trashwall#

trashwall# tcpdump -ni fxp0 host 208.83.71.138
tcpdump: listening on fxp0, link-type EN10MB
10:04:55.599135 74.199.15.89 > 208.83.71.138: icmp: echo request
10:04:56.607387 74.199.15.89 > 208.83.71.138: icmp: echo request
10:04:57.617325 74.199.15.89 > 208.83.71.138: icmp: echo request
10:04:58.627298 74.199.15.89 > 208.83.71.138: icmp: echo request
10:04:59.637270 74.199.15.89 > 208.83.71.138: icmp: echo request
10:05:00.647255 74.199.15.89 > 208.83.71.138: icmp: echo request

trashwall# tcpdump -ni fxp1 host 208.83.71.138
tcpdump: listening on fxp1, link-type EN10MB
10:04:55.624511 208.83.71.138 > 74.199.15.89: icmp: echo reply
10:04:56.626254 208.83.71.138 > 74.199.15.89: icmp: echo reply
10:04:57.636455 208.83.71.138 > 74.199.15.89: icmp: echo reply
10:04:58.645461 208.83.71.138 > 74.199.15.89: icmp: echo reply
10:04:59.657185 208.83.71.138 > 74.199.15.89: icmp: echo reply
10:05:00.667090 208.83.71.138 > 74.199.15.89: icmp: echo reply

Is it possible that maybe I should just have both IPs bound to fxp0? This will require me to make the dhcp stuff quite a bit more custom, but maybe it’ll work?

UPDATE: This fixes it:

binat on fxp1 from $reason to any -> fxp1
nat on fxp0 from $reason to any -> fxp1 static-port

Thanks to for the help with this. I’ve now integrated into my normal config and will be updating the Trashwall article soon to detail how I’m using the new WOW! connection at home. See this post for information on how this was used to make Xbox Live work properly (open NAT) from behind PF.

Leave a Reply