I use the OpenBSD PF (packet filter) firewall at home to protect the systems I run, and to provide access to a few services over the Internet. The services I make accessible to the Internet run on servers in RFC 1918 address space, which requires my OpenBSD gateway to perform translate IP addresses and apply inbound filter policies for the services I expose. The PF documentation describes how to do this, but I thought I would share the setup I use in case folks are interested.
To begin, you should define one or more tables and macros to make your firewall rule file easier to manage. The following example sets up one table with a list of IP addresses we want to allow to access the services we run on our network, and one macro with the external interface of the firewall:
# External interface
$ `ext = "hme1"`
# Define a table with acceptable IP addresses
table <work> { 1.2.3.4/32, 1.2.3.5/32 }
Once the tables and macros are setup, you will need to add a redirect statement to translate the DST IP address to the RFC 1918 address your server is using for each TCP segment that matches the policy (i.e. all requests from to TCP port 443):
# NAT the DST IP in all HTTPS connections from <work>
rdr on $ext proto tcp from <work> to X.X.X.X port 443 ->
192.168.100.100 port 443
Now that the redirect statement is in place (you will need to change X.X.X.X to the external IP address of your firewall), we can define a rule to allow connections to the server that runs the secure web server:
# Allow HTTPS connections
pass in quick on $ext proto tcp from <work> to 192.168.100.100 port
443 keep state
Once you add the pass statement, you can test connectivity by pointing your web browser to the IP address of your firewall. I could have used a single rdr statement to NAT and filter the traffic, but I like to split these up to make things easier to read.