ctx->guides->proxy

Accessing firewalled services using PF on OpenBSD

Consider a scenario where all hosts in a network have public IP addresses, but only one subnet is accessible from the Internet because of a corporate firewall. Internal hosts communicate with each other normally. In order to access the SSH port of a firewalled machine, say with the hostname hidden, you may use another host, say middle, belonging in the accessible subnet, at a different port, and redirect traffic to and from hidden. Most of this is described in PF User’s Guide, but the manual assumes a public and a private interface with NAT between the two. This guide is about using the same interface to do the forwarding. It can be done using a user-level proxy or completely in-kernel with PF. The configuration of the middle host is found below.

User-level proxy with inetd and netcat

/etc/pf.conf:

# Proxy SSH to other machines with inetd
pass in quick on egress proto tcp from any to any port 1337 rdr-to (lo)

/etc/inetd.conf:

# SSH proxy using nc
127.0.0.1:1337 stream tcp nowait proxy /usr/bin/nc nc hidden 22

/etc/rc.conf.local:

inetd_flags=

Kernel-level proxy only with PF rules

/etc/pf.conf:

# Proxy SSH to other machines
pass in quick on egress proto tcp to port 1337 rdr-to hidden port ssh
pass out quick on egress proto tcp to hidden port ssh nat-to (egress)

/etc/sysctl.conf:

net.inet.ip.forwarding=1

Tips for SSH access

For seamless SSH access to the hidden host you can alias it to the middle host, and use the appropriate port like this.

~/.ssh/config:

Host hidden
    HostName middle
    Port 1337

The aliasing can also be done at the /etc/hosts or DNS level using a CNAME record for hidden.example.org that points to middle.example.org and use:

~/.ssh/config:

Host hidden.example.org
    Port 1337

Performance evaluation

A rough benchmarking of the two methods shows that the PF-only setup performs slightly better probably because it generates less local traffic and context switches. Throughput and latency was measured over ssh as shown below. The tests are a single large file transfer and the timing of login and logout. The load on the middle host is also displayed broken down as interrupts and system time.

# large file transfer
$ time scp install54.iso hidden:

# login operation
$ time ssh hidden echo

And the results:

#            throughput   latency   ints  system
user-level:     3.9MB/s   0.6461s    35%      5%
kernel-only:    3.9MB/s   0.6220s    23%      0%

Choose your destiny!

Cheers!

lostd@