2

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.

5
  • You have to set up an alias IP on the OpenBSD box son that the box receives the traffic for this IP. I think otherwise the IP cannot be bound to a MAC address. Thereby no PC can answer your request. Jun 20, 2012 at 17:24
  • The OpenBSD box does not need to receive the traffic for this IP - I am only interested in doing the NAT for locally originated connections. In short, what we are doing is: ssh -L1234:fake-ip:6789 openbsd-box, should work, as well as ssh -L1234:real-ip:6789 openbsd-box.
    – chutz
    Jul 6, 2012 at 16:27
  • Sure but you know that someone has to answer for the ARP requests. If no PC has this particular IP then there will be no routing and the request can't be rerouted be the OpenBSD box. The IP HAS to be in the network somewhere or oyu have to define a static route. Jul 6, 2012 at 16:44
  • That's why I am looking for a NAT that is going to translate the fake IP to a real one. Keep in mind that what I am looking for is doable with iptables on Linux.
    – chutz
    Jul 7, 2012 at 17:44
  • I don't know why it works with iptables. Would you ,for the sake of science, try if the rules work when you add an alias for the old ip on any interface? Jul 7, 2012 at 18:05

2 Answers 2

1

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
8
  • This is what I am referring to in my question when I say "rdr rules that include the -> symbol". Unfortunately OpenBSD 4.7 does not seem to support this syntax anymore. I simply get /etc/pf.conf:19: syntax error with your example.
    – chutz
    Jun 20, 2012 at 14:28
  • Okay I took a quick look into the OpenBSD manpages. And will edit my post. Jun 20, 2012 at 14:32
  • Thanks, but it doesn't seem to be doing the trick for me. I am trying to redirect packets that originate locally on the machine. So when I am on the OpenBSD machine itself, I expect to apply the rule and then be able to ping both OLD_IP and NEW_IP. I updated my question to clarify more what I am trying.
    – chutz
    Jun 20, 2012 at 14:37
  • This is what the rule should do. It should redirect the ICMP packages sent to the old IP to the new IP. It does not touch the new IP. Jun 20, 2012 at 14:39
  • Well, not working: sudo pfctl -s rules pass in on em0 proto icmp from any to 10.68.99.99 rdr-to 10.68.32.215 ping -c1 10.68.32.215 - works ping -c1 10.68.99.99 - nothing
    – chutz
    Jun 20, 2012 at 14:48
0

I don't think pf can do this. pf has 4 ways to alter packets:

  • A packet filter rule with a route-to (and reply-to) option
    • This only alters the packet's route and not the actual destination
  • A nat rule
    • This only alters an outgoing packet's source address/port
  • A binat rule
    • This only alters an outgoing packet's source address/port and an incoming packet's destination address/port.
    • (Since rdr is stateful, I don't understand why binat exists.)
  • A rdr rule
    • This only alters an incoming packet's destination address/port

I was trying to redirect outgoing packets with destination 10.193.130.31.56862 to 10.0.0.30.56862. I was able to do this on linux with iptables:

sudo iptables -t nat -A OUTPUT -d 10.193.130.31 -p tcp --dport 56862 -j DNAT --to-destination 10.0.0.30

I tried to do the same on macOS by adding to my /etc/pf.conf:

nat pass log (all) on en6 inet proto tcp from any to 10.193.130.31 port 56862 -> 10.0.0.30 port 56862

where en6 is my external network interface.

I then added a logging interface with:

sudo ifconfig pflog0 create

Finally, I reloaded my pf rules with:

sudo pfctl -vf /etc/pf.conf

And started pf with:

sudo pfctl -e

And then my packets with tcpdump:

sudo tcpdump 'tcp port 56862' -vv -lnttti en6

I created a test connection with:

nc -v 10.193.130.31 56862

And I saw the following output in tcpdump:

00:00:00.000000 rule 1/0(match): nat out on en6: (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 64)
  10.0.0.30.56862 > 10.193.130.31.56862: Flags [SEW], cksum 0x9730 (incorrect -> 0xd1e3), seq 3809148311, win 65535, options [mss 8961,nop,wscale 9,nop,nop,TS val 2314373431 ecr 0,sackOK,eol], length 0

Which indicates that my source was changed to 10.0.0.30:56862, but not my destination.

When I ran similar tests with an rdr rule, I got no output (because I had no incoming packets):

rdr pass inet proto tcp from any to 10.193.130.31 port 56862 -> 10.0.0.30 port 56862

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .