Linux Firewall

This page only cover firewall on Linux, mostly for use as host-based firewall. For network-edge, dedicated firewall such as Check Point and Pix, see net.html#firewall


Linux kernel 2.2  - ipchains
Linux kernel 2.4  - iptables 
Linux kernel 4.18? - nftables (rhel8 anyway)

/etc/sysconfig/iptables         # firewall rule config file

system-config-firewall          # GUI tool to set iptables firewall rules
firewall-config                 # use this instead of above in RHEL7 (since it use shorewalls)

ufw				# UI for Ubuntu-land
iptables		# CLI for RHEL6
firewall-cmd	# CLI for RHEL7

firewalld is the UI in RHEL7 and RHEL8.  But RHEL8 no longer use iptables, but instead use nftables (still netfilter at kernel level).

ufw, iptables and firewalld typically manipulate the INPUT chain.  
Docker mangle with iptables also, and typically does it at the PREROUTING chain, thus containerers could be inadvertendly open to the world, "above" firewalld control.  
DOCKER-USER chain can be used, see below.



Chains:
  • PreRouting
  • Forward
  • Input
  • Output
  • PostRouting

  • Tables (not all chains has all tables):
  • filter
  • nat
  • mangle
  • contrack (connection tracking, aka security?)




  • Ref:
    1. Additional iptables diagram collection by nerdalert
    2. depth guide from booleanworld
    3. Digital Ocean deep dive

    IPTables

    As a command that front end kernel 2.4 netfileter. Comes standard in CentOS 6/7.
    It is not a daemon, ps won't show anything. It configure netfilter in the kernel. lsmod will show a kernel modules.
    systemctl enable  iptables
    systemctl start   iptables		# it run /etc/sysconfig/network/iptables, configure netfileter in the kernel, and done.
    					# there are no daemon left running.  don't look for iptables in 'ps'
    systemctl restart iptables		# reload firewall rule.  If there are error, system auto stop and don't change existing rule.
    journalct -xe				# see log message, esp if iptables config is wrong and can't be loaded.
    
    sudo iptables -L			# show summary of configured chain.  
    
    echo "service iptables restart" | at now + 5 minutes	# schedule a restart of firewall via atq
    echo "systemctl stop iptables"  | at 18:30		# atq; atrm ... and remove it once iptables works
    
    # example /etc/sysconfig/iptables that get loaded at boot (CentOS 7)
    # pretty much block everything.  
    # allow specific ssh in
    # allows for ping
    # all outbound is allowed
     
    *filter
    :INPUT ACCEPT [0:0]
    :FORWARD ACCEPT [0:0]
    :OUTPUT ACCEPT [0:0]
    -A INPUT -m state --state ESTABLISHED,RELATED             -j ACCEPT
    -A INPUT -p icmp -m icmp --icmp-type parameter-problem    -j REJECT --reject-with icmp-host-prohibited
    -A INPUT -p icmp -m icmp --icmp-type redirect             -j REJECT --reject-with icmp-host-prohibited
    -A INPUT -p icmp -m icmp --icmp-type router-advertisement -j REJECT --reject-with icmp-host-prohibited
    -A INPUT -p icmp -m icmp --icmp-type router-solicitation  -j REJECT --reject-with icmp-host-prohibited
    -A INPUT -p icmp -m icmp --icmp-type source-quench        -j REJECT --reject-with icmp-host-prohibited
    -A INPUT -p icmp -m icmp --icmp-type time-exceeded        -j REJECT --reject-with icmp-host-prohibited
    -A INPUT -p icmp -j ACCEPT
    -A INPUT -i lo   -j ACCEPT
    ## -i lo  is for input interface loopback  
    ##-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT	# this will allow ALL inbound ssh
    -A INPUT -s 10.11.12.88 -p tcp --dport 22 -j ACCEPT			# this allow only a list of IP to ssh in
    -A INPUT -s 10.11.12.89 -p tcp --dport 22 -j ACCEPT -m comment --comment "comment that show up in iptables -L" 
    -A INPUT -p tcp --dport 22 -j DROP
    ## default is reject, and no pkt forwarding
    -A INPUT   -j REJECT --reject-with icmp-host-prohibited
    -A FORWARD -j REJECT --reject-with icmp-host-prohibited
    COMMIT
    
    
    Config file is really a series of arguments to the iptables command.
    Commands are executed sequentially, as a chain.
    But feel like updating /etc/sysconfig/iptables and then running systemctl restart iptables is easier (and safer). If it drops ssh, at least the rule will run and re-enable inbound ssh to log back in...
    Maybe good for some temporary testing, especially those not involving ssh :)
    Ref: CentOS wiki ipTables (basic overview/simple example)
    
    
    iptables -P INPUT ACCEPT			# (temp) set policy to accept (or else connected ssh will drop)
    
    iptables -F					# flush out all existing rules.  if ssh in, that connection will be dropped (unless with above)
    
    -A INPUT					# add/append to the INPUT chain rule.
    -m state					# load the state-full inspection Module
    	 --state ESTABLISHED,RELATED		# state could be NEW, ESTABLISHED or RELATED 
    						# RELATED allow fw to see if it part of an already ongoing connection
    
    -m tcp			## ??
    
    -p tcp						# protocol tcp
    --dport 22					# destination port 
    --sport 6000-7000				# source ports range
    
    -j ACCEPT					# action is to allow the packet thru
    
    iptables -A INPUT -s 192.168.0.0/24 -j ACCEPT  			# using standard slash notation
    iptables -A INPUT -s 192.168.0.0/255.255.255.0 -j ACCEPT 	# using a subnet mask
    
    iptables -P FORWARD DROP					# ends with a DROP rule by default if not already allowed
    
    
    iptables -L -v -n				# List the rules -n: numeric, -v:
    
    
    /sbin/service iptables save			# calls /sbin/iptables-save (to /etc/sysconfig/iptables)
    						# if don't do this, iptables at cli will be lost after reboot
    
    
    Allowing SSH, NIS
    Core snipplet allowing SSH,NIS for a list of hosts.
    Other packets are rejected with ICMP message, rather silently dropped. Log goes to syslog, at kern.6 level.
    
    *filter
    :INPUT DROP [0:0]	## seems like can start with DROP and still works fine (when read from file, cut-n-paste may not)
    :FORWARD DROP [0:0]	## if use DROP instead of ACCEPT, the icmp msg may not happen.
    :OUTPUT ACCEPT [0:0]
    
    ## log incoming traffic, for temporary debugging only.  will create massive logs!
    ## log to kernel.*.  0=emergency, 4=warning, 7=debug
    ## -A INPUT -p tcp -j LOG --log-prefix "IPTables Packet IN: " --log-level 7
    ## -A INPUT -p tcp -s 123.4.130.157 -j LOG --log-prefix "IPTables Packet IN: " --log-level 7
    
    -A INPUT -i lo -j ACCEPT
    
    # NFS.  
    # https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/storage_administration_guide/s2-nfs-nfs-firewall-config
    # edit /etc/sysconfig/nfs 
    #MOUNTD_PORT=2049   # Controls which TCP and UDP port mountd (rpc.mountd) uses.  # must be specified
    #STATD_PORT=port    # Controls which TCP and UDP port status (rpc.statd) uses.   # can live without
    #LOCKD_TCPPORT=port # Controls which TCP port nlockmgr (lockd) uses.   		# can live without
    #LOCKD_UDPPORT=port # Controls which UDP port nlockmgr (lockd) uses.   		# can live without
    # systemctl restart nfs-config # rhel 7 only
    # rpcinfo -p nfsserver shows:
    #    100005    3   udp  20048  mountd          # /etc/services specify port 20048
    #    100005    3   tcp  20048  mountd
    #    100003    3   tcp   2049  nfs
    # 2049 was historically needed by nfs, but needed to allow 20048 for rocky 8.6, it also allows showmount  # xref exa5
    -A INPUT -s 123.4.7.196          -p tcp -m multiport --dports 22,111,2049,20048  -j ACCEPT -m comment --comment "RPC and NFS for ex5"
    
    #### Port 22 allows inbound ssh 
    #### NIS uses multiple ports: 111 (portmapper), 837-837 (set YP* args in /etc/default/nis for ubuntu.  /etc/sysconfig/network for centos)
    #### seems like can live with just TCP version of these ports, may not need to allow udp for newer clients.
    #### https://help.ubuntu.com/community/SettingUpNISHowTo
    #### NFS uses multiple ports as well (in addition to portmapper 111):  1110, 2049, 4045.  
    #### /etc/sysconfig/nfs for centos5 https://www.centos.org/docs/5/html/5.2/Deployment_Guide/s2-sysconfig-nfs.html
    #### though this config not currently exporting NFS (yet)
    #### https://superuser.com/questions/667690/iptables-rules-for-nfs
    #### Can use a comma separated of source IP, or just add one host IP per line for easy removal
    #### /var/yp/securenets need to list nis client ip if securenet is configured.  restart ypserv.
    #### netstat -tulpn
    
    -A INPUT -s 123.4.7.25          -p tcp -m multiport --dports 22,111,834,835,836,837  -j ACCEPT
    -A INPUT -s 123.4.7.25          -p udp -m multiport --dports    111,834,835,836,837  -j ACCEPT
    
    
    ####
    ####  log dropped/rejected packets to kernel.6
    ####  but multicast/broadcast packets are simply dropped
    ####
    -A INPUT -d 255.255.255.255 -j DROP 
    -A INPUT -d 123.4.7.255     -j DROP 
    -A INPUT -d 224.0.0.0/24    -j DROP 
    -A INPUT -j LOG -m limit --limit 2/min --log-prefix "IPTables_reject/drop: " --log-level 6
    
    ###
    ### alt method to logging, chained rule, don't seems to be necessary
    ###
    ##?-N LOGGING
    ##?-A INPUT -j LOGGING
    ##?-A LOGGING -m limit --limit 2/min -j LOG --log-prefix "IPTables Packet Dropped: " --log-level 6
    ##?-A LOGGING -j REJECT --reject-with icmp-host-prohibited
    ##--A LOGGING -j DROP
    
    ####
    ####  default to drop/reject packet.  No Packet forwarding.
    ####
    -A INPUT   -j REJECT --reject-with icmp-host-prohibited
    -A FORWARD -j REJECT --reject-with icmp-host-prohibited
    COMMIT
    
    
    Allowing Samba
    ## https://www.samba.org/~tpot/articles/firewall.html
    ## ports to allow samba
    -A INPUT -s 192.168.1.0/24 -p tcp --dport 139 -j ACCEPT
    -A INPUT -s 192.168.1.0/24 -p tcp --dport 445 -j ACCEPT
    ## these next 2 are needed for NETBIOS browsing of computer over the network.  
    ## if can live without browsing, don't need to enable them
    ##-A INPUT -s 192.168.1.0/24 -p udp --dport 137 -j ACCEPT
    ##-A INPUT -s 192.168.1.0/24 -p udp --dport 138 -j ACCEPT
    
    Port Fowarding
    Port forward incoming traffic hitting on port 80, sending it to port 8000.
    iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8000
    
    This works when i use a different machine to hit port 8000, then the PREROUTING will take place and forward to port 80.
    But, it will not work when I am connecting within the machine, even when IP address is used. this is relevant sometime when you the requestor come from the same machine (eg if you are doing development work and testing on the same machine)
    [ommitting the -i eth0 may get it to forward traffic even when it is on the same host?]
    One-off manipulation
    Not recommended unless in niche circumstances.
    # allow for established connection
    iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
    
    # ensure default policy is to drop (else need to explicitly define a drop rule at the end of the chain)
    iptables -P INPUT   DROP
    iptables -P FORWARD DROP
    
    
    iptables -A INPUT -s 73.170.217.126/32  -p tcp --dport 80   -j ACCEPT -m comment --comment "-A appends as last rule of the chain"
    iptables -I INPUT -s 73.170.217.126/32  -p tcp --dport 80   -j LOG    -m comment --comment "-I insert as first rule of the chain"
    	# -j LOG will trigger log mechanism, and jump back when done
    
    iptables -nvL --line-n 		# list rule with index number
    iptables -D INPUT 1			# delete index 1 of INPUT chain
    
    
    # custom chain to LOG and DROP connection 
    iptables -N LOG_AND_DROP
    iptables -A LOG_AND_DROP -j LOG --log-prefix "IPTables Source host denied " --log-level 7
    iptables -A LOG_AND_DROP -j DROP		# add as last rule to default to log and then drop packet not otherwise already allowed
    
    
    iptables -S         # also get custom chains (eg those created by docker, ufw, etc)
    
    iptables -X INPUT   # remove all INPUT chain (so default to allow all; unless policy (-D) is drop?  or that get reset as well?)
    iptables -F         # flush all rules (iptables still active, but largely allow all)
    
    

    firewalld

    RHEL7 default to firewalld. It allows for programmatic way of configureing netfilter. The config file is XML. But configuration is typically done by firewall-cmd cli and there is no need to muck with the XML files directly. Firewalld does generate IPTABLES commands, but does not use the /etc/sysconfig/iptables file. Those who likes the iptables cli would feel very foreign with firewalld and vice versa.
    firewalld also run as a dynamic firewall service, and thus has a daemon. The daemon works with NetworkManager, determining zones the network is and apply firewall rules accordingly (public WiFi would be in a zone with more restrictions than home network.
    For a given system, either use the iptables (service) or firewalld. Pick one and stick to it.



    firewalld out of the box comes with a number of zones pre-created. But by and large, there is no pre-defined "pathway" on how packet travels. It is not necessarily that "inside" zone will always go to "public" zone.
    Think of zone as grouping traffic together, and sys admin add target of what this group as a whole should do. target: default simply means keep processin the target thru the other chain. If no rules define that a packet should be dropped, then it would be allowed thru to the user process. In practice, at least on linux server, arget: default would mostly lead to ACCEPT. If desire is to block such traffice, it tends to become target: DROP (or %%REJECT%%).
    But other target action can be done, either in the zone itself (eg accept) or later chains (eg NAT, port forward, etc).
    Refer to the firewall.html#tables_chains_diagram

    ref: firewalls.org zone options
    system-config-firewall		# for static rule config of firewalld
    firewall-config			# ?? gui??
    systemctl status firewalld
    
    
    
    cf in 
    /usr/lib/firewallD	hold zone config, rules, etc.
    /etc/firewalld/... 	system config.  bunch of xml files.
    
    
    firewall-cmd --list-all-zones					# like UFW, can support zones like public, private, etc.
    
    firewall-cmd --get-active-zones
    firewall-cmd --get-default-zone
    
    firewall-cmd --zone=public --list-all				# list all rules that is applicable to the "public" zone
    
    
    
    firewall-cmd --get-services					# list canned service like httpd
    
    firewall-cmd --zone=public --add-port=4000/tcp            	# allow port 4000 from anywhere, runtime
    firewall-cmd --zone=public --add-port=4000/tcp --permanent	# allow port 4000 from anywhere, config
    
    firewall-cmd --zone=public --remove-port=4000/tcp            	# undo the add above
    
    firewall-cmd --reload						# read from config, presumably drop anything that is runtime and not in --permanent
    
    firewall-cmd --runtime-to-permanent			# save config that were done without --permanent
    
    firewall-cmd --direct --get-all-chains				# direct interaction with iptables
    firewall-cmd --direct --get-all-rules
    
    
    # eg for removing subnet or host from a specific zone
    firewall-cmd --zone=internal --remove-source 128.3.0.0/16 --permanent
    firewall-cmd --zone=trusted  --remove-source 128.3.7.87   --permanent
    firewall-cmd --zone=trusted  --remove-source 128.3.7.87                # rm running config is more important
    ## ansible add it to internal
    
    
    
    ref: Linode intro to firewallD on CentOS

    XML
    Reading configuration of firewalld may actually be easier on the xml file than output of firewall-cmd or iptables.
    For CentOS 7, config files are stored in /etc/firewalld/zones.
    If using tools to insert rules into xml files, may need to delete them by hand. afterwards, may need to run ptables -X ; iptables -F; iptables -Z to truely reset/remove old entries that does not wish to be still allowed

    Example config snipplet, which include "rich rules" (iptables rules within a firewalld zone) conf/firewalld_public.xml

    Precedence
    1. Sources (list of IP) are processed first.
    2. Interfaces (eg eno1, enp94s0f0) are applied second
    3. In a zone, target: default means kick the packet upstair (typically means ACCEPT if the service is listed, DROP/REJECT otherise?)
    4. the default zone is not the same as target: default default zone is often what Network Manager assign when the network is joined. firewalld allow explicitly defining which one is the default zone (eg set it to DMZ)
    5. iptables -S would be good friend for debugging
    6. rich rules are low level iptable rules, not recommended in firewallD, unless no pre-defined service for it. it is processed within a zone.
    
    
    
    ref: 
    
    
    
    
    tmp
    public.xml firewalld direct edit of
    
      {rule family="ipv4"}
        {source address="10.229.192.0/24" /}
        {service name="ssh" /}
        {accept/}
      {/rule}
    
      {rule family="ipv4"}
        {source address="10.229.192.0/24" /}
        {to-port="104" /}
        {accept/}
      {/rule}
    
    
    firewall-cmd --list-all-zones output, clauses are mostly AND conditions for traffic to flow.
    ie IP list, ports. These are AND condition.
    services, ports. These are OR coditions. so equiv to 22 or HTTPS for below example.
    If interfaces are listed, it will be AND condition with IP ranges?
    eg below only allow traffic to port 443 for ip of 10.15.x.x and 192.168.1.x
    *sigh* this is why I am not a huge fan of firewalld...
    internal (active)
      target: default
      icmp-block-inversion: no
      interfaces:
      sources: 10.15.0.0/16 192.168.1.0/24
      services: ssh
      ports: 443/tcp
      protocols:
      forward: no
      masquerade: no
      forward-ports:
      source-ports:
      icmp-blocks:
      rich rules:
    
    Masquerade/NAT
    
    Masquerade (ie, perform NAT):
    eg Simple NAT-router, route internal zone traffic with RFC 1918 private IP range to public zone (internet).
    Just need to add masquerade to the public zone, ie perform NAT on all packets coming in and out.
    
    firewall-cmd --add-masquerade --zone=public --permanent
    
    
    DNAT = Destination NAT.   Think of Port forwarding.
    eg Expose web server to the public world.
    
    firewall-cmd --permanent --zone=public --add-forward-port=port=80:proto=tcp:toport=80:toaddr=192.168.199.10
    
    
    
    ref:

    nftables

    net filter tables

    In RHEL8, iptables commands need to be translated to nftables.
    ref: RH Doc NFTables

    system with firewalld configured, systemctl status nftables can/should still be inactive/dead state. config files would go to /etc/nftables .

    iptables -nvL on rhel8 machine configured with firewall-cmd will no longer show relevant info as it did in rhel7 system
    could try nft list ruleset
    
    iptables-translate [iptables-chain-cmd]    	# generate nft equiv cmd (not always avail)
    
    nft list ruleset
    nft list table inet firewalld		# everything?
    nft list table ip   firewalld		# ipv4 only
    nft list table ip6  firewalld
    
    
    

    ufw/gufw

    Uncomplicated firewall.
    This come std with Ubuntu (eg 14.04, 16.04). There are can rules in place, but the firewall service is not enabled by default.

    UFW is one of the easiest fw UI to use. front end to iptables commands?

    gufw is a GUI front end. Comes with default profile for Home, Office, Public, which (presumably) are progressively more stringent firewall
    gufw is reasonably easy to use, though it is a java thing, so kinda sluggish. It also generate lots of rules, so result not as easy to read/manage using the CLI. So, if use GUFW, stick to it.
    sudo apt-get install gufw   # the gui isn't installed by default
    

    Ref: Ubuntu UFW page

    Example Barebone Config
    
    # reset all firewall settings.  ufw auto creates backup
    # seems okay to do this when ssh in, won't be dropped.
    sudo ufw reset		
    
    # allow inbound ssh for select subnet, comma list NOT supported
    sudo ufw allow from 192.168.188.0/24 to any port 22 proto tcp
    sudo ufw allow from 172.3.0.0/16     to any port 22 proto tcp 
    
    # allow inbound ssh for the whole internet, ip v4 only
    sudo ufw allow from 0.0.0.0/0        to any port 22 proto tcp 
    
    # allow specific subnet inbound access to samba (ufw app in /etc/ufw/applications.d/)
    sudo ufw allow from 192.168.188.0/24  to any app samba
    
    # allow one specific remote host full access
    sudo ufw allow from 192.168.188.118  to any 
    sudo ufw enable
    
    # no explicit save command needed, rules auto update to /lib/ufw/user.rules
    
    
    
    # get an idea of what ufw wrote
    # ufw has a set of pre-defined rules that it would apply automagically
    iptables -L | grep ACCEPT   
    
    # Note: CANNOT vi /lib/usr/user.rules and hope to get ufw to re-read the update rules via
    # ufw reload 
    #
    # NOT even: 
    # ufw disable; vi users.rules; ufw enable
    # 
    # NOT even vi /lib/usr/user.rules and reboot
    # in general, don't edit the users.rules file.  
    # Not sure how to restore from the backup it makes...
    
    
    UFW writes into iptables-restore copatible text files. Fine tuning can be done by editing:
    1. /etc/default/ufw # high level config, default rules, drop INVALID, incoming, etc.
    2. /etc/ufw/before.rules # these are very much like iptables command, except keyword is ufw-... ?
    3. /etc/ufw/after.rules
    4. /etc/ufw/sysctl.conf
    5. /var/lib/ufw/user.rules
    6. /lib/ufw/user.rules # link to /etc/ufw/user.rules
    7. ...
    More details at Ubuntu UFW wiki

    Simple Usage
    sudo ufw allow http/tcp		# allow port 80/tcp for IPv4 and IPv6
    sudo ufw logging on
    sudo ufw enable
    sudo ufw status
    sudo ufw status numbered
    sudo service ufw status
    
    Random Examples of More Complex Usage
    sudo ufw status verbose
    sudo ufw status numbered
    
    sudo ufw show raw		#
    sudo ufw disable
    sudo ufw --dry-run enable
    sudo ufw --dry-run reload
    sudo ufw reset			# ??
    sudo ufw app list|info...	# ??
    
    sudo ufw allow 80		# assume incoming, but allow both udp and tcp
    sudo ufw allow 53/tcp		# specify allow tcp only
    
    sudo ufw deny 53/udp		# deny rule
    sudo ufw delete deny 53/udp	# remove deny rule
    
    
    sudo ufw allow from 10.11.12.0/24 			# allow subnet, all traffic
    sudo ufw allow from 10.11.12.8 to any port 22		# outbound allow traffic (any refers to host's IP [and not protocol?])
    
    sudo ufw allow proto tcp from any to 10.11.12.8 port 22	
    sudo ufw rule comment 'ssh listen on 10.11.12.8:22, allow inbound from everywhere(any)'
    ## comment clause don't seems to work, don't remember where i read it from
    
    sudo ufw allow 53 comment 'allow DNS on 53 (tcp and udp)'
    sudo ufw allow proto tcp from any to any port 80,443 comment 'http + https'
    
    
    sudo ufw deny from 8.8.8.8				# explicity deny of a specific host (or subnet)
    
    
    Numbered Rules
    ufw, like iptables, have numbered rules (it is a netfilter thing)
    sudo ufw status numbered
    sudo ufw delete 1
    sudo ufw insert 1 allow from 123.45.6.77
    
    # rules can be deleted by number or prefix "delete" in front of the rule
    sudo ufw        allow from 192.168.188.0/24 to any port 22 proto tcp
    sudo ufw delete allow from 192.168.188.0/24 to any port 22 proto tcp
    
    
    IPSec is supported by using the 'esp' ('50') and 'ah' ('51') protocols.

    Ref: Ubuntu community UFW page

    docker

    Docker does a lot of network stuff, and manipulate iptables directly.
    1. Daemon is open to everyone. To restrict access, see Docker iptables doc
      iptables -I DOCKER-USER -i ext_if ! -s 10.0.22.0/24 -j DROP
    2. Docker add lots of iptables to route traffic from host to container. And it does so at the PREROUTING chain, thereby bypassing most of FirewallD or UFW rules
    3. Add custom rule to DOCKER-USER chain to regulate what flows into container. Avail with Docker 17.06 (not in RHEL7 rpm, need to use docker-ce).
    4. Unrouted describe the addition of a custom chain FILTER and feed both DOCKER and regular physical host traffic into it for centralized control. This could be good for single host use, likely need other approach for a farm of servers running docker
    5. Note that DOCKER-USER chain is NAT-ed, thus may need to use the IP of the container
    6. serverfault post

    Router


    A network router almost always has firewall running these days.
    For dedicated network-edge firewall such as Check Point and Pix, see net.html#firewall
    This section will cover the use of IPTables on linux to make a "home-made" firewall/router.
    Shorewall maybe the way to go for such project. But NAT rules using iptables commands is provided below.

    Shorewall

    Shoreline Firewall. It is a UI/front end for various kernel level netfilter. Replaces the command line iptables. (can produce iptables config file?).
    Kinda complicated, not sure if it makes it any easier to use that "iptables" commands for simple config. For building a firewall appliance, then it would be the way to go. eg. Firewall with Samba exception

    Shorewall Intro, explaining zones, interfaces/ip tuple, etc essentially to understand shorewall. It is not anything like iptables command.

    Router with NAT using IPTables

    To make the linux box act as a router using iptables NAT (eg HPC head node routing for compute nodes)
    First enable kernel forward:
    vi /etc/sysctl.conf
    net.ipv4.ip_forward=1
    Then update iptables.
    eg: (ref: https://www.revsys.com/writings/quicktips/nat.html )
    	# enp1s0f0 = private internal network, inbound traffic to be forwarded
    	# eno1     = public network, outbound traffic
    
    	# remove any drop forward rules in /etc/sysconfig/iptables
    	systemctl restart iptables
    	iptables-save > iptables.save.beforeNat
        	iptables -t nat -A POSTROUTING  -o eno1                                          -j MASQUERADE
        	iptables -A FORWARD -i eno1     -o enp1s0f0 -m state --state RELATED,ESTABLISHED -j ACCEPT
        	iptables -A FORWARD -i enp1s0f0 -o eno1                                          -j ACCEPT
            iptables-save > iptables.save.afterNat 
    	cp iptables-afterNat /etc/sysconfig/iptables	# save for next reboot 
    
    	# or update /etc/syconfig/iptablesconfig and have it save changes on stop or restart...
    	# i don't like that method.
    
    eg as direct edit to /etc/sysconfig/iptables.
    can ignore numbers such as :PREROUTING ACCEPT [1204:124820]
    at boot, they seems to be state info.
    Some packet may get dropped during a restart... ?
    but works :)
    ## /etc/sysconfig/iptables direct edit so that it survive reboot ## 
    *nat :PREROUTING ACCEPT [0:0] :INPUT ACCEPT [0:0] :OUTPUT ACCEPT [0:0] :POSTROUTING ACCEPT [0:0] -A POSTROUTING -o eno1 -j MASQUERADE COMMIT #### #### Regular firewall settings except for some forward rule at the end #### *filter :INPUT DROP [0:0] :FORWARD DROP [0:0] :OUTPUT ACCEPT [0:0] -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT -A INPUT -i lo -j ACCEPT -A INPUT -s 10.0.0.0/8 -p tcp --dport 22 -j ACCEPT -m comment --comment "ALLOW ssh for internal network" # add more rules here as desired #### #### default to drop/reject packet. #### -A INPUT -j REJECT --reject-with icmp-host-prohibited #### #### Headnode does packet forward ie NAT router #### ##-A FORWARD -j REJECT --reject-with icmp-host-prohibited -A FORWARD -i eno1 -o enp1s0f0 -m state --state RELATED,ESTABLISHED -j ACCEPT -A FORWARD -i enp1s0f0 -o eno1 -j ACCEPT COMMIT

    NAT with IPTables


    This is a condensed version of NAT tutorial by karlrupp
          IN   /------------\     /---------\  fwd pkt   /-------------\  OUT
        ------>| PREROUTING |---->| ROUTING |----------->| POSTROUTING |-------->
               \------------/     \---------/            \-------------/
    
        # Abstract structure of an iptables instruction:
        iptables [-t table] command [match pattern] [action]
        # default is "-t filter"
    
    Prep
       # IMPORTANT: Activate IP-forwarding in the kernel!
    
       # Disabled by default!
       $ echo "1" > /proc/sys/net/ipv4/ip_forward
    
       vi /etc/sysctl.conf 
       net.ipv4.ip_forward=1
       sysctl -p /etc/sysctl.conf           # reread conf file and activate changes
    
       sysctl -w net.ipv4.ip_forward=1	# RHEL4 stuff?  no longer work?
    
       # Load various modules. Usually they are already loaded
       # (especially for newer kernels), in that case
       # the following commands are not needed.
        
       # Load iptables module:
       $ modprobe ip_tables
       
       # activate connection tracking
       # (connection's status are taken into account)
       $ modprobe ip_conntrack
    
    Outbound
    Connect a LAN to the internet (ie, outbound traffic) eg1:
        	iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE
    
    Inbound
    1. Running a Server behind a NAT-router
    2. For servers running behind a NAT-router additional steps are needed since at first you cannot connect from outside to the server.
    3. Let us assume that we have a HTTP-server with IP 192.168.1.2 and
    4. our router has the IP address 192.168.1.1 (eth0?) and is connected to the internet over its second network interface with IP 123.123.123.123 (eth1?).
    5. DNAT = Destination NAT
    6. To reach the HTTP-server from outside, type
        iptables -t nat -A PREROUTING -p tcp -i eth1 --dport 80 -j DNAT --to 192.168.1.2
    
    Multihosts Inbound NAT
    # ref http://linux-ip.net/html/nat-dnat.html # eth1 is internet connection on the router
    # inbound nat all ports
    iptables -t nat -A PREROUTING -i eth1 -d 13.24.231.10 -j DNAT --to-destination 172.0.2.8
    
    # inbound nat for RR 12.83.7.15[1-3] (ssh only, not sure if safe)
    iptables -t nat -A PREROUTING -p tcp -i eth1 -d 12.83.7.151 --dport 22 -j DNAT --to-destination 172.0.2.0
    iptables -t nat -A PREROUTING -p tcp -i eth1 -d 12.83.7.152 --dport 22 -j DNAT --to-destination 172.0.2.1
    iptables -t nat -A PREROUTING -p tcp -i eth1 -d 12.83.7.153 --dport 22 -j DNAT --to-destination 172.0.2.2
    
    
    

    Firewall on Mac/BSD

    Mac 10.5 default to a port of OpenBSD's PF.
    Older IPFW cli tool from FreeBSD is from 10.2 days.
    See apple.html#firewall


    [Doc URL: http://tin6150.github.io/psg/firewall.html ]
    Last Updated: 2017-06-08
    (cc) Tin Ho. See main page for copyright info.


    hoti1
    sn5050
    psg101 sn50 tin6150