OpenBSD pf – implementing the equivalent of an iptables DNAT

openbsdpf

Short version

Server A (OpenBSD 4.7) connects to server B (Windows). IP of server B changes. Server A should be able to connect to server B to both the old and new IP. We cannot configure multiple IPs on server B.

Long version

We have an OpenBSD server acting as an access point (ssh + authpf rules) where external clients connect and then open a connection to a service on another internal server. The internal server IP is going to change.

To give us more time to reconfigure all clients to use the new IP address, I thought we can implement the equivalent of a DNAT on the OpenBSD box. If this was a Linux box, I could use the following DNAT rule which lets me connect out from the box itself to the remote service on either the real IP (10.68.32.215) or the new IP.

$ sudo iptables -t nat -A OUTPUT -d 10.68.99.99 -j DNAT --to-dest 10.68.32.215
$ ssh-keyscan -t rsa 10.68.32.215
# 10.68.32.215 SSH-2.0-OpenSSH_4.3
10.68.32.215 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAy/GCd47aaRkBOu72v9Ysqk48Ngd6budStvdwnvMOTLiYoz6M81cTq7SskWctXx57cz6Ijnv1sbzcmDpFMUsN5vHk+6NxfrLzO0M1zh7UezY54FakgaavSdCiy15vGw/Lifntp5kMKkjgC5o42O+RUVw5iCpR8nsu/2/kR2smcVR1G3R8EunjCZWEptOCHz3Iup7FTMd4Pw/xmt+8u+5ZyHKu+uaLWQl6I12rzLiQJNyMLVdhba54FGiJDFUfcXtgM7cFli6xlrE3dnbboQE/7/cuj/N11QwTvHuU07NtrubefZE1VahWb146ph31blsW5NSiyFwL2I7rxFFoPQMbuQ==
$ ssh-keyscan -t rsa 10.68.99.99
# 10.68.99.99 SSH-2.0-OpenSSH_4.3
10.68.99.99 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAy/GCd47aaRkBOu72v9Ysqk48Ngd6budStvdwnvMOTLiYoz6M81cTq7SskWctXx57cz6Ijnv1sbzcmDpFMUsN5vHk+6NxfrLzO0M1zh7UezY54FakgaavSdCiy15vGw/Lifntp5kMKkjgC5o42O+RUVw5iCpR8nsu/2/kR2smcVR1G3R8EunjCZWEptOCHz3Iup7FTMd4Pw/xmt+8u+5ZyHKu+uaLWQl6I12rzLiQJNyMLVdhba54FGiJDFUfcXtgM7cFli6xlrE3dnbboQE/7/cuj/N11QwTvHuU07NtrubefZE1VahWb146ph31blsW5NSiyFwL2I7rxFFoPQMbuQ==

Our version of OpenBSD is 4.7, but we can upgrade if necessary.
If this DNAT is not possible we can probably do a NAT on a firewall along the way.

The closest I was able to accomplish on a test box is:

pass out on em1 inet proto icmp from any to 10.68.31.99 nat-to 10.68.31.247

Unfortunately, pfctl -s state tells me that nat-to translates the source IP, while I need to translate the destination.

$ sudo pfctl -s state
all icmp 10.68.31.247:7263 (10.68.30.199:13437) -> 10.68.31.99:8       0:0

I also found lots of mentions about rules that start with rdr and include the -> symbol to express the translation, but it looks like this syntax has been obsoleted in 4.7 and I cannot get anything similar to work. Attempts to implement a new-syntax redirect rule fail with:

$ echo match out on em1 to 10.68.31.99 rdr-to 10.68.31.247 | sudo pfctl -f -
stdin:1: rdr-to can only be used inbound

Of course, since I am trying to redirect outgoing traffic, modifying the above rule to "pass in" does not work either.

Current status

Ended up applying a NAT on a firewall between the two servers. Did the trick, though from academic interest, I am still curious if this is doable in OpenBSD.

Best Answer

I'm not totally sure if that's what you want but I use something likt this to redirect traffic to another IP.

rdr pass on $ext_if proto icmp from any to $OLD_IP -> $NEW_IP

The syntax is not tested but might work

Something similar works on FreeBSD


Edit

After a look into the OpenBSD manpages this syntax might work:

pass in on $ext_if proto icmp from any to $OLD_IP rdr-to $NEW_IP
Related Topic