Filtering is not necessarily needed for the front-facing interface, as long as you bind your SSH daemon to the internal interface –or– when the gateway doesn’t listen on any port what-so-ever e.g. as a XEN guest.
Enable IP Forwarding
sysctl net.inet.ip.forwarding sysctl -w net.inet.ip.forwarding=1 cp -pi /etc/sysctl.conf /etc/sysctl.conf.dist vi /etc/sysctl.conf net.inet.ip.forwarding=1
vi /etc/ipnat.conf # new file map PUBLIC-NIC SUBNET/24 -> PUBLIC-IP/32 proxy port ftp ftp/tcp map PUBLIC-NIC SUBNET/24 -> PUBLIC-IP/32 portmap tcp/udp 10000:20000 map PUBLIC-NIC SUBNET/24 -> PUBLIC-IP/32
As for masquerading, define
0/32 as public IP.
rdr PUBLIC-NIC PUBLIC-IP/32 port 80 -> INTERNAL-IP port 80 rdr PUBLIC-NIC PUBLIC_IP/32 port 443 -> INTERNAL-IP port 443
vi /etc/ipf.conf # NetBSD vi /etc/ipf.rules # FreeBSD block in all block out all # loopback pass in quick on lo0 all pass out quick on lo0 all # internal interface pass in quick on wm1 all pass out quick on wm1 all # icmp pass in quick proto icmp pass out quick proto icmp
quick string allows to force the rule whatever comes next.
Note on Solaris,
lo0 cannot be filtered anyhow.
# ssh from the outside (inside is allowed already) pass in on wm0 proto tcp from any to any port = 2222 keep state
pass out on wm0 proto udp from any port > 1024 to any port = 53 keep state pass out on wm0 proto tcp from any port > 1024 to any port = 53 keep state pass out on wm0 proto tcp from any port > 1024 to any port = 80 keep state pass out on wm0 proto tcp from any port > 1024 to any port = 443 keep state
vi /etc/rc.conf ipnat=yes ipmon=yes ipmon_flags="-Dns" ipfilter=yes ipfilter_flags="" /etc/rc.d/ipnat restart /etc/rc.d/ipmon restart /etc/rc.d/ipfilter restart
and reload the rules with
/etc/rc.d/ipnat reload /etc/rc.d/ipfilter reload # ipf -Fa -f /etc/ipf.conf
show the active ruleset
vi /etc/rc.conf ipfilter_enable="YES" # Start ipf firewall ipfilter_rules="/etc/ipf.rules" # loads rules definition text file ipmon_enable="YES" # Start IP monitor log ipmon_flags="-Ds" # D = start as daemon # s = log to syslog # v = log tcp window, ack, seq # n = map IP & port to names service ipmon start service ipfilter start
and reload the rules with
ipf -Fa -f /etc/ipf.rules
In case you just need to filter the public network interface, start right off with it instead of messing with a default global policy. This actually prevents you from changing the configuration whatever you do with bridges, agregates and other internal virtual or physical network interfaces. It also keeps the loopback free already.
# NIC-specific policy block in on em0 all block out on em0 all pass in quick proto icmp pass out quick proto icmp
To secure even more, you may add those rules at the top
block in from any to 255.255.255.255 block in from any to 127.0.0.1/32
block in log first on em0 all block out log first on em0 all
eventually tell syslogd to send filter logs to some place else
vi /etc/syslog.conf *.emerg * *.*;local0.none -/var/log/messages local0.* -/var/log/ipfilter touch /var/log/ipfilter chmod 640 /var/log/messages chmod 640 /var/log/ipfilter /etc/rc.d/syslogd restart
It’s preferable to drop the packets as attackers' port scanners will need significantly more time to complete. But I prefer to reject them instead of dropping them so one immediately knows when the port is unavailable instead of waiting for a timeout.
If you want to answer properly that a TCP or UDP port is closed instead of dropping, here’s an attempt
block in all block return-icmp in all block return-icmp-as-dest(port-unr) in proto udp all block return-rst in proto tcp all block out all block return-icmp out all block return-icmp-as-dest(port-unr) out proto udp all block return-rst out proto tcp all
problem is, it will appear as
closed and it makes it even harder to troubelshoot than
filtered, in the end, as you would think the daemon is not listening on the target host.
pass in quick proto icmp from any to any icmp-type echo pass in quick proto icmp from any to any icmp-type echorep pass out quick proto icmp from any to any icmp-type echo pass out quick proto icmp from any to any icmp-type echorep
keep frags to prevent
flags S to drop fragmented packets
pass in on em0 proto tcp from any to any port = 2222 flags S keep state keep frags
block in log quick on em0 from ATTACKER-IP to any
For a passive FTP capable server, you need to open port 21 (not 20, used for active FTP) and a port range e.g.
pass in on hme0 proto tcp from any to any port = 21 keep state pass in on hme0 proto tcp from any to any port 49999 >< 51000 keep state
this means port 50000 to 50999 can be used by the FTP daemons behind the NAT.
tcp/udp 137 #netbios-ns tcp/udp 138 #netbios-dgm tcp/udp 139 #netbios-ssn #tcp/udp 81 # hosts2 name server
pass in quick proto udp from any to any port = ike pass in quick proto udp from any to any port = 4500 pass in proto esp from any to any
pass in quick proto udp from any to port = route pass in quick proto icmp from any to any icmp-type 9 # routeradvert pass in quick proto igmp from any to any
IP Filter FAQ https://www.phildev.net/ipf/ https://www.phildev.net/ipf/long.html https://www.phildev.net/ipf/IPFques.html
A simple NAT (“IP Masquerading”) setup https://www.netbsd.org/docs/network/#simplenat
31.5. IPFILTER (IPF) https://docs.freebsd.org/en_US.ISO8859-1/books/handbook/firewalls-ipf.html
ipf, ipf.conf - IPFilter firewall rules file format https://www.freebsd.org/cgi/man.cgi?query=ipf
ipf, ipf.conf– IP packet filter rule syntax https://docs.oracle.com/cd/E19253-01/816-5174/6mbb98ufa/index.html
Creating and Editing IP Filter Configuration Files https://docs.oracle.com/cd/E23824_01/html/821-1453/ipfilter-admin-2.html
HP-UX IPFilter Version A.03.05.13 Administrator’s Guide http://docshare01.docshare.tips/files/24972/249724030.pdf
ipfilter hpux11.11 https://www.unix.com/hp-ux/60466-ipfilter-hpux11-11-a.html https://www.unix.com/302186070-post3.html
HP-UX IPFilter V18.0 Administrator GuideHP-UX 11i v3 https://support.hpe.com/hpesc/public/docDisplay?docId=c02752836