This page is an extension of the firewall overview page of the user's guide.
It describes with more details how to manage and configure the firewall:

  • Disable firewall over reboot
  • Modify the firewall rules and persist the rules

We will not describe how iptables and ip6tables work since there is a lot of documentation available on internet but rather describe how they are integrated in the LORIX OS and how they can be managed from a system point of view.

Enable and disable firewall (persistent)

As described in the user's guide, the firewall service can be started and stopped for the current session.

Starting and stopping a service is however not really considered as "enabling/disabling" the service since it's just a temporary state.
On next reboot, the service will start as usual even if it has been stopped during the last session.

Starting or stopping a service doesn't make this action persistent over a reboot.

If you want to learn more about the "start/stop vs enable/disable" concept, please consult the more advanced service management documentation.

As a shortcut, the following section describes how to enable and disable the firewall over reboot, as a persistent state.

Enable the firewall at boot

The firewall is already configured to run at boot by default on the LORIX OS but if you have disabled this service, you can enable it again using the following command:

Enable the firewall at boot

sudo rc-update add iptables default
BASH

Result

lorix-one-aabbcc:~$ sudo rc-update add iptables default
 * service iptables added to runlevel default
BASH

Enable the firewall at boot

sudo rc-update add ip6tables default
BASH

Result

lorix-one-aabbcc:~$ sudo rc-update add ip6tables default
 * service ip6tables added to runlevel default
BASH

Enable is not start

Please note that enabling the service (start at boot) will not make it immediately start. You still need to run the command sudo rc-service <service> start.

Disable the firewall at boot

You can avoid starting the firewall at boot with the following command:

Disable the firewall at boot

sudo rc-update del iptables default
BASH

Result

lorix-one-aabbcc:~$ sudo rc-update del iptables default
 * service iptables removed from runlevel default
BASH

Disable the firewall at boot

sudo rc-update del ip6tables default
BASH

Result

lorix-one-aabbcc:~$ sudo rc-update del ip6tables default
 * service ip6tables removed from runlevel default
BASH

Disable is not stop

Please note that disabling the service (no start at boot) will not make it immediately stop. You still need to run the command sudo rc-service <service> stop.

Configure the firewall

Workflow and data state

As explained previously, the ip[6]tables rules are stored in the files /etc/iptables/ip[6]tables.rules. When the firewall services are started, the iptables and ip6tables applications are loaded with the rules from these files.

There is then two ways of modifying the rules:

  1. Use directly iptables and ip6tables to modify the rules in memory and save the result in the files
    This is the preferred way, the syntax follows documentation and rules are applied directly
  2. Edit directly the rule files and restart the services to load the new rules
    This is not the preferred way since the rule files use a specific syntax which is less documented

Modify the rules in place with iptables (preferred way)

Ensure firewall is running

To modify the rules using ip[6]tables, the corresponding service need to run first of all, if you stopped it, ensure it's running:

Enable the firewall

sudo rc-service iptables start
BASH

Enable the firewall

sudo rc-service ip6tables start
BASH

Edit the rules

You can then use standard iptables and ip6tables commands using available documentation on internet:

Be careful when modifying the rules since they are immediately applied and some of them could stop connections like SSH.

Any firewall modification should always be done using the USB access or at least done when this access is possible.

For example, the following command display the actual running rules:

Show current firewall rules

sudo iptables -L -n -v --line-numbers 
BASH

Result

gw150b2n7:~$ sudo iptables -L -n -v --line-numbers 
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1     1030  153K ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0            /* Accept everything on loopback */
2        0     0 ACCEPT     all  --  usb0   *       0.0.0.0/0            0.0.0.0/0            /* Accept everything on usb0 */
3        2   104 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0            state INVALID
4        0     0 ACCEPT     all  --  *      *       127.0.0.1            127.0.0.1           
5        0     0 DROP       all  --  !lo    *       127.0.0.0/8          0.0.0.0/0           
6        0     0 PINGPROTECT  icmp --  *      *       0.0.0.0/0            0.0.0.0/0            icmptype 8 /* Must stay before ACCEPT for ESTABLISHED */
7      849 58967 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED
8        0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0            icmptype 3
9        0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0            icmptype 11
10       0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0            icmptype 12
11       0     0 ACCEPT     udp  --  *      *       0.0.0.0/0            0.0.0.0/0            udp spt:5353
12       1    60 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:80 flags:0x17/0x02 state NEW
13       0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:443 flags:0x17/0x02 state NEW
14       0     0 SSHPROTECT  tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:22 state NEW
15      79 10184 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 1748 packets, 244K bytes)
num   pkts bytes target     prot opt in     out     source               destination         

Chain PINGPROTECT (1 references)
num   pkts bytes target     prot opt in     out     source               destination         
1        0     0            all  --  *      *       0.0.0.0/0            0.0.0.0/0            recent: SET name: PING side: source mask: 255.255.255.255 /* PING: Only 10 tries per source IP per second */
2        0     0 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0            recent: UPDATE seconds: 1 hit_count: 10 TTL-Match name: PING side: source mask: 255.255.255.255
3        0     0 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain SSHPROTECT (1 references)
num   pkts bytes target     prot opt in     out     source               destination         
1        0     0            all  --  *      *       0.0.0.0/0            0.0.0.0/0            recent: SET name: SSH side: source mask: 255.255.255.255 /* SSH: Only 4 tries per source IP per minute */
2        0     0 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0            recent: UPDATE seconds: 60 hit_count: 4 name: SSH side: source mask: 255.255.255.255
3        0     0 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0    
BASH

Show current firewall rules

sudo ip6tables -L -n -v --line-numbers 
BASH

Result

gw150b2n7:~$ sudo ip6tables -L -n -v --line-numbers 
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1        8   944 ACCEPT     all      lo     *       ::/0                 ::/0                
2        0     0 DROP       all      *      *       ::/0                 ::/0                 state INVALID
3        0     0 ACCEPT     all      *      *       ::1                  ::1                 
4        0     0 DROP       all      !lo    *       ::1                  ::/0                
5        0     0 PINGPROTECT  icmpv6    *      *       ::/0                 ::/0                 ipv6-icmptype 128 /* Must stay before ACCEPT for ESTABLISHED */
6        0     0 ACCEPT     all      *      *       ::/0                 ::/0                 state RELATED,ESTABLISHED
7        0     0 ACCEPT     icmpv6    *      *       ::/0                 ::/0                 ipv6-icmptype 1 /* RFC 4890 */
8        0     0 ACCEPT     icmpv6    *      *       ::/0                 ::/0                 ipv6-icmptype 2 /* RFC 4890 */
9        0     0 ACCEPT     icmpv6    *      *       ::/0                 ::/0                 ipv6-icmptype 3 /* RFC 4890 */
10       0     0 ACCEPT     icmpv6    *      *       ::/0                 ::/0                 ipv6-icmptype 4 /* RFC 4890 */
11       0     0 ACCEPT     icmpv6    *      *       ::/0                 ::/0                 ipv6-icmptype 133 HL match HL == 255 /* RFC 4890 */
12       0     0 ACCEPT     icmpv6    *      *       ::/0                 ::/0                 ipv6-icmptype 134 HL match HL == 255 /* RFC 4890 */
13       0     0 ACCEPT     icmpv6    *      *       ::/0                 ::/0                 ipv6-icmptype 135 HL match HL == 255 /* RFC 4890 */
14       0     0 ACCEPT     icmpv6    *      *       ::/0                 ::/0                 ipv6-icmptype 136 HL match HL == 255 /* RFC 4890 */
15       0     0 ACCEPT     icmpv6    *      *       ::/0                 ::/0                 ipv6-icmptype 137 HL match HL == 255 /* RFC 4890 */
16       0     0 ACCEPT     icmpv6    *      *       ::/0                 ::/0                 ipv6-icmptype 141 HL match HL == 255 /* RFC 4890 */
17       0     0 ACCEPT     icmpv6    *      *       ::/0                 ::/0                 ipv6-icmptype 142 HL match HL == 255 /* RFC 4890 */
18       0     0 ACCEPT     icmpv6    *      *       fe80::/10            ::/0                 ipv6-icmptype 130 /* RFC 4890 */
19       0     0 ACCEPT     icmpv6    *      *       fe80::/10            ::/0                 ipv6-icmptype 131 /* RFC 4890 */
20       0     0 ACCEPT     icmpv6    *      *       fe80::/10            ::/0                 ipv6-icmptype 132 /* RFC 4890 */
21       0     0 ACCEPT     icmpv6    *      *       fe80::/10            ::/0                 ipv6-icmptype 143 /* RFC 4890 */
22       0     0 ACCEPT     icmpv6    *      *       ::/0                 ::/0                 ipv6-icmptype 148 HL match HL == 255 /* RFC 4890 */
23       0     0 ACCEPT     icmpv6    *      *       ::/0                 ::/0                 ipv6-icmptype 149 HL match HL == 255 /* RFC 4890 */
24       0     0 ACCEPT     icmpv6    *      *       fe80::/10            ::/0                 ipv6-icmptype 151 HL match HL == 1 /* RFC 4890 */
25       0     0 ACCEPT     icmpv6    *      *       fe80::/10            ::/0                 ipv6-icmptype 152 HL match HL == 1 /* RFC 4890 */
26       0     0 ACCEPT     icmpv6    *      *       fe80::/10            ::/0                 ipv6-icmptype 153 HL match HL == 1 /* RFC 4890 */
27       8  1526 ACCEPT     udp      *      *       ::/0                 ::/0                 udp spt:5353
28       0     0 ACCEPT     tcp      *      *       ::/0                 ::/0                 tcp dpt:80 flags:0x17/0x02 state NEW
29       0     0 ACCEPT     tcp      *      *       ::/0                 ::/0                 tcp dpt:443 flags:0x17/0x02 state NEW
30       0     0 SSHPROTECT  tcp      *      *       ::/0                 ::/0                 tcp dpt:22 state NEW
31   19996 3869K DROP       all      *      *       ::/0                 ::/0                

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 191 packets, 10226 bytes)
num   pkts bytes target     prot opt in     out     source               destination         

Chain PINGPROTECT (1 references)
num   pkts bytes target     prot opt in     out     source               destination         
1        0     0            all      *      *       ::/0                 ::/0                 recent: SET name: PING side: source mask: ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff /* PING: Only 10 tries per source IP per second */
2        0     0 DROP       all      *      *       ::/0                 ::/0                 recent: UPDATE seconds: 1 hit_count: 10 TTL-Match name: PING side: source mask: ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
3        0     0 ACCEPT     all      *      *       ::/0                 ::/0                

Chain SSHPROTECT (1 references)
num   pkts bytes target     prot opt in     out     source               destination         
1        0     0            all      *      *       ::/0                 ::/0                 recent: SET name: SSH side: source mask: ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff /* SSH: Only 4 tries per source IP per minute */
2        0     0 DROP       all      *      *       ::/0                 ::/0                 recent: UPDATE seconds: 60 hit_count: 4 name: SSH side: source mask: ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
3        0     0 ACCEPT     all      *      *       ::/0                 ::/0   
BASH

Check the iptables documentation for the available commands for modifications.

E.g. to delete a rule, use (where 12 is the num of the rule from the previous output):

sudo iptables -D INPUT 12
CODE

Save the rules

Once you have done your modifications in the running rules, you can save them in the persistent rule files:

Save the rules

sudo rc-service iptables save
BASH

Result

lorix-one-aabbcc:~$ sudo rc-service iptables save
iptables         | * Saving iptables state ...
BASH

Save the rules

sudo rc-service ip6tables save
BASH

Result

lorix-one-aabbcc:~$ sudo rc-service ip6tables save
ip6tables        | * Saving ip6tables state ...
BASH

From there, the rules have been saved to the corresponding file and will be reloaded each time the firewall service is started.
No need to reload the service since the rules are already loaded in the firewall.

Modify the rule configuration files

Service state

The service doesn't need to be started or stopped at this point since we will only edit the rule file and reload it into the running service.

Modify the rule file

You can edit the rule files using your favorite editor:

Edit the rule file

sudo nano /etc/iptables/iptables.rules
BASH

Default file content

*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:PINGPROTECT - [0:0]
:SSHPROTECT - [0:0]

# Accept everything on loopback
[0:0] -A INPUT -i lo -j ACCEPT

# Drop non-conforming packets, such as malformed headers, etc.
[0:0] -A INPUT -m state --state INVALID -j DROP

# Accept everything on localhost to localhost
[0:0] -A INPUT -s 127.0.0.1 -d 127.0.0.1 -j ACCEPT

# Block remote packets claiming to be from a loopback address.
[0:0] -A INPUT -s 127.0.0.0/8 ! -i lo -j DROP

# Accept ICMP (echo-request) before accept all ESTABLISHED connection
[0:0] -A INPUT -p icmp -m icmp --icmp-type echo-request -m comment --comment "Must stay before ACCEPT for ESTABLISHED" -j PINGPROTECT

# Accept already existing connections
[0:0] -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

# Accept ICMP (destination-unreachable, time-exceeded, parameter-problem)
[0:0] -A INPUT -p icmp -m icmp --icmp-type destination-unreachable -j ACCEPT
[0:0] -A INPUT -p icmp -m icmp --icmp-type time-exceeded -j ACCEPT
[0:0] -A INPUT -p icmp -m icmp --icmp-type parameter-problem -j ACCEPT

# Accept mDNS
[0:0] -A INPUT -p udp -m udp --sport 5353 -j ACCEPT

# Accept HTTP and HTTPS
[0:0] -A INPUT -p tcp -m tcp --dport 80 --tcp-flags FIN,SYN,RST,ACK SYN -m state --state NEW -j ACCEPT
[0:0] -A INPUT -p tcp -m tcp --dport 443 --tcp-flags FIN,SYN,RST,ACK SYN -m state --state NEW -j ACCEPT

# Accept SSH with brute force protection
[0:0] -A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -j SSHPROTECT

# Drop the rest for the INPUT chain
[0:0] -A INPUT -j DROP

# Manage ping protection PINGPROTECT chain
[0:0] -A PINGPROTECT -m recent --name PING --set --rsource -m comment --comment "PING: Only 10 tries per source IP per second"
[0:0] -A PINGPROTECT -m recent --name PING --update --seconds 1 --hitcount 10 --rttl --rsource -j DROP
[0:0] -A PINGPROTECT -j ACCEPT

# Manage SSH protection SSHPROTECT chain
[0:0] -A SSHPROTECT -m recent --set --name SSH --rsource -m comment --comment "SSH: Only 4 tries per source IP per minute"
[0:0] -A SSHPROTECT -m recent --update --seconds 60 --hitcount 4 --name SSH --rsource -j DROP
[0:0] -A SSHPROTECT -j ACCEPT

COMMIT
BASH

Edit the rule file

sudo nano /etc/iptables/ip6tables.rules
BASH

Default file content

# Generated by ip6tables-save v1.8.4 on Mon Aug 10 15:14:59 2020
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [64:8779]
:PINGPROTECT - [0:0]
:SSHPROTECT - [0:0]
[0:0] -A INPUT -i lo -j ACCEPT
[0:0] -A INPUT -m state --state INVALID -j DROP
[0:0] -A INPUT -s ::1/128 -d ::1/128 -j ACCEPT
[0:0] -A INPUT -s ::1/128 ! -i lo -j DROP
[0:0] -A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 128 -m comment --comment "Must stay before ACCEPT for ESTABLISHED" -j PINGPROTECT
[0:0] -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
[0:0] -A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 1 -m comment --comment "RFC 4890" -j ACCEPT
[0:0] -A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 2 -m comment --comment "RFC 4890" -j ACCEPT
[0:0] -A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 3 -m comment --comment "RFC 4890" -j ACCEPT
[0:0] -A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 4 -m comment --comment "RFC 4890" -j ACCEPT
[0:0] -A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 133 -m hl --hl-eq 255 -m comment --comment "RFC 4890" -j ACCEPT
[0:0] -A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 134 -m hl --hl-eq 255 -m comment --comment "RFC 4890" -j ACCEPT
[0:0] -A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 135 -m hl --hl-eq 255 -m comment --comment "RFC 4890" -j ACCEPT
[0:0] -A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 136 -m hl --hl-eq 255 -m comment --comment "RFC 4890" -j ACCEPT
[0:0] -A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 137 -m hl --hl-eq 255 -m comment --comment "RFC 4890" -j ACCEPT
[0:0] -A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 141 -m hl --hl-eq 255 -m comment --comment "RFC 4890" -j ACCEPT
[0:0] -A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 142 -m hl --hl-eq 255 -m comment --comment "RFC 4890" -j ACCEPT
[0:0] -A INPUT -s fe80::/10 -p ipv6-icmp -m icmp6 --icmpv6-type 130 -m comment --comment "RFC 4890" -j ACCEPT
[0:0] -A INPUT -s fe80::/10 -p ipv6-icmp -m icmp6 --icmpv6-type 131 -m comment --comment "RFC 4890" -j ACCEPT
[0:0] -A INPUT -s fe80::/10 -p ipv6-icmp -m icmp6 --icmpv6-type 132 -m comment --comment "RFC 4890" -j ACCEPT
[0:0] -A INPUT -s fe80::/10 -p ipv6-icmp -m icmp6 --icmpv6-type 143 -m comment --comment "RFC 4890" -j ACCEPT
[0:0] -A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 148 -m hl --hl-eq 255 -m comment --comment "RFC 4890" -j ACCEPT
[0:0] -A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 149 -m hl --hl-eq 255 -m comment --comment "RFC 4890" -j ACCEPT
[0:0] -A INPUT -s fe80::/10 -p ipv6-icmp -m icmp6 --icmpv6-type 151 -m hl --hl-eq 1 -m comment --comment "RFC 4890" -j ACCEPT
[0:0] -A INPUT -s fe80::/10 -p ipv6-icmp -m icmp6 --icmpv6-type 152 -m hl --hl-eq 1 -m comment --comment "RFC 4890" -j ACCEPT
[0:0] -A INPUT -s fe80::/10 -p ipv6-icmp -m icmp6 --icmpv6-type 153 -m hl --hl-eq 1 -m comment --comment "RFC 4890" -j ACCEPT
[0:0] -A INPUT -p udp -m udp --sport 5353 -j ACCEPT
[0:0] -A INPUT -p tcp -m tcp --dport 80 --tcp-flags FIN,SYN,RST,ACK SYN -m state --state NEW -j ACCEPT
[0:0] -A INPUT -p tcp -m tcp --dport 443 --tcp-flags FIN,SYN,RST,ACK SYN -m state --state NEW -j ACCEPT
[0:0] -A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -j SSHPROTECT
[0:0] -A INPUT -j DROP
[0:0] -A PINGPROTECT -m recent --set --name PING --mask ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff --rsource -m comment --comment "PING: Only 10 tries per source IP per second"
[0:0] -A PINGPROTECT -m recent --update --seconds 1 --hitcount 10 --rttl --name PING --mask ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff --rsource -j DROP
[0:0] -A PINGPROTECT -j ACCEPT
[0:0] -A SSHPROTECT -m recent --set --name SSH --mask ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff --rsource -m comment --comment "SSH: Only 4 tries per source IP per minute"
[0:0] -A SSHPROTECT -m recent --update --seconds 60 --hitcount 4 --name SSH --mask ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff --rsource -j DROP
[0:0] -A SSHPROTECT -j ACCEPT
COMMIT
# Completed on Mon Aug 10 15:14:59 2020
# Generated by ip6tables-save v1.8.4 on Mon Aug 10 15:14:59 2020
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [12:1350]
:POSTROUTING ACCEPT [12:1350]
COMMIT
BASH

As you can see, the content of the file is difficult to read and most of all, if you insert an error inside, ip[6]tables will not be able to load it:

Wrong format error

lorix-one-aabbcc:~$ sudo rc-service iptables start
iptables         | * Loading iptables state and starting firewall ...
iptables         |Bad argument `test'
iptables         |Error occurred at line: 19
iptables         |Try `iptables-restore -h' or 'iptables-restore --help' for more information.   [ !! ]
iptables         | * ERROR: iptables failed to start
BASH

Reload the rules into the firewall

The rules are persisted into the rule files but not loaded into the running application. To load them, you need to (re)start the firewall service:

Load the rules

sudo rc-service iptables restart
BASH

Result

lorix-one-aabbcc:~$ sudo rc-service iptables restart
iptables         | * Stopping firewall ...                                        [ ok ]
iptables         | * Loading iptables state and starting firewall ...
BASH

Load the rules

sudo rc-service ip6tables restart
BASH

Result

lorix-one-aabbcc:~$ sudo rc-service ip6tables restart
ip6tables        | * Stopping firewall ...                                        [ ok ]
ip6tables        | * Loading ip6tables state and starting firewall ...
BASH