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 

/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


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
-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 -p tcp --dport 22 -j ACCEPT			# this allow only a list of IP to ssh in
-A INPUT -s -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

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
						# 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 -j ACCEPT  			# using standard slash notation
iptables -A INPUT -s -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.

: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.

## log incoming traffic, for temporary debugging only.  will create massive logs!
## -A INPUT -p tcp -j LOG --log-prefix "IPTables Packet IN: " --log-level 7
## -A INPUT -p tcp -s -j LOG --log-prefix "IPTables Packet IN: " --log-level 7

-A INPUT -i lo -j ACCEPT

#### 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.
#### NFS uses multiple ports as well (in addition to portmapper 111):  1110, 2049, 4045.  
#### /etc/sysconfig/nfs for centos5
#### though this config not currently exporting NFS (yet)
#### 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          -p tcp -m multiport --dports 22,111,834,835,836,837  -j ACCEPT
-A INPUT -s          -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 -j DROP 
-A INPUT -d     -j DROP 
-A INPUT -d    -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
##?-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

####  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

Allowing Samba
## ports to allow samba
-A INPUT -s -p tcp --dport 139 -j ACCEPT
-A INPUT -s -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 -p udp --dport 137 -j ACCEPT
##-A INPUT -s -p udp --dport 138 -j ACCEPT
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?]


RHEL7 also ship with firewalld. It allows for programmatic way of configureing netfilter. The config file is XML. It 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.

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 --direct --get-all-chains				# direct interaction with iptables
firewall-cmd --direct --get-all-rules

ref: Linode intro to firewallD on CentOS


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 to any port 22 proto tcp
sudo ufw allow from     to any port 22 proto tcp 

# allow inbound ssh for the whole internet, ip v4 only
sudo ufw allow from        to any port 22 proto tcp 

# allow specific subnet inbound access to samba (ufw app in /etc/ufw/applications.d/)
sudo ufw allow from  to any app samba

# allow one specific remote host full access
sudo ufw allow from  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 			# allow subnet, all traffic
sudo ufw allow from to any port 22		# outbound allow traffic (any refers to host's IP [and not protocol?])

sudo ufw allow proto tcp from any to port 22	
sudo ufw rule comment 'ssh listen on, 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				# 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

# rules can be deleted by number or prefix "delete" in front of the rule
sudo ufw        allow from to any port 22 proto tcp
sudo ufw delete allow from to any port 22 proto tcp

IPSec is supported by using the 'esp' ('50') and 'ah' ('51') protocols.

Ref: Ubuntu community UFW page


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.


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
Then update iptables.
eg: (ref: )
	# 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 -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 > 
	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 -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"
   # IMPORTANT: Activate IP-forwarding in the kernel!

   # Disabled by default!
   $ echo "1" > /proc/sys/net/ipv4/ip_forward

   vi /etc/sysctl.conf 
   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
Connect a LAN to the internet (ie, outbound traffic) eg1:
    	iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE
  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 and
  4. our router has the IP address (eth0?) and is connected to the internet over its second network interface with IP (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
Multihosts Inbound NAT
# ref # eth1 is internet connection on the router
# inbound nat all ports
iptables -t nat -A PREROUTING -i eth1 -d -j DNAT --to-destination

# inbound nat for RR[1-3] (ssh only, not sure if safe)
iptables -t nat -A PREROUTING -p tcp -i eth1 -d --dport 22 -j DNAT --to-destination
iptables -t nat -A PREROUTING -p tcp -i eth1 -d --dport 22 -j DNAT --to-destination
iptables -t nat -A PREROUTING -p tcp -i eth1 -d --dport 22 -j DNAT --to-destination

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


Check to allow user login is really a convoluted matrix of many different combinations. All the different "if ssh, if user is foo, login in from bar, etc etc" is now coded in pam.d.
Very often, new authentication source is configured via nsswitch.conf
Whether ssh keys are allowed as authentication source is set in:
- sshd.conf (if certain users are allowed to use ssh key, others are not)
- pam sshd config (forcing interactive login?) (if config is same for all users) ??


Each file correspond to configuration used for that specific service.
sshd	# used when ssh in to the machine
login	# used to /bin/login (eg, login in the terminal?  Also in local X11?)

su	# when running su command
sudo 	# when running sudo command

system-auth	# often refered by other config file to use it.  think of this as C's #include.
config-util	# refered by many system config tools, such as system-config-network




In increasing mandatory necessity:

optional ?

sufficient ??

	use content of another config file (eg system-auth, config-util)
	think of #include of C

	Failure also results in denial of authentication, 
	although PAM will still call all the other modules listed for this service 
	before denying authentication. 
	*** think of it as mandatory but keep checking anyway ??!! ***

	Failure to authenticate via this module results in immediate denial of authentication. 
	*** think of as mandatory, waste no more time, fail right away ***


# Use a radius authentication server listed in a config file
auth       required conf=/etc/raddb/server	

# When SELinux operates in Permissive mode, 
# disable linux user login for users listed in /etc/security/sepermit.conf
# If user not listed, would still be allowed to login when selinux is disabled or in permissive mode
auth       required

# if file /etc/nologin exist, user not allowed to login
account    required

# use/allow for system password auth  ??
account    include      password-auth

# traditional unix auth, usually /etc/passwd, /etc/shadow


[Doc URL: ]
Last Updated: 2017-06-08
(cc) Tin Ho. See main page for copyright info.

psg101 sn50 tin6150