Applies to openSUSE Leap 15

16 Masquerading and Firewalls

Whenever Linux is used in a network environment, you can use the kernel functions that allow the manipulation of network packets to maintain a separation between internal and external network areas. The Linux netfilter framework provides the means to establish an effective firewall that keeps different networks apart. Using iptables—a generic table structure for the definition of rule sets—precisely controls the packets allowed to pass a network interface. Such a packet filter can be set up using firewalld and its graphical interface firewall-config.

16.1 Packet Filtering with iptables

This section discusses the low-level details of packet filtering. The components netfilter and iptables are responsible for the filtering and manipulation of network packets and for network address translation (NAT). The filtering criteria and any actions associated with them are stored in chains, which must be matched one after another by individual network packets as they arrive. The chains to match are stored in tables. The iptables command allows you to alter these tables and rule sets.

The Linux kernel maintains three tables, each for a particular category of functions of the packet filter:

filter

This table holds the bulk of the filter rules, because it implements the packet filtering mechanism in the stricter sense, which determines whether packets are let through (ACCEPT) or discarded (DROP), for example.

nat

This table defines any changes to the source and target addresses of packets. Using these functions also allows you to implement masquerading, which is a special case of NAT used to link a private network with the Internet.

mangle

The rules held in this table make it possible to manipulate values stored in IP headers (such as the type of service).

These tables contain several predefined chains to match packets:

PREROUTING

This chain is applied to all incoming packets.

INPUT

This chain is applied to packets destined for the system's internal processes.

FORWARD

This chain is applied to packets that are only routed through the system.

OUTPUT

This chain is applied to packets originating from the system itself.

POSTROUTING

This chain is applied to all outgoing packets.

Figure 16.1, “iptables: A Packet's Possible Paths” illustrates the paths along which a network packet may travel on a given system. For the sake of simplicity, the figure lists tables as parts of chains, but in reality these chains are held within the tables themselves.

In the simplest case, an incoming packet destined for the system itself arrives at the eth0 interface. The packet is first referred to the PREROUTING chain of the mangle table then to the PREROUTING chain of the nat table. The following step, concerning the routing of the packet, determines that the actual target of the packet is a process of the system itself. After passing the INPUT chains of the mangle and the filter table, the packet finally reaches its target, provided that the rules of the filter table allow this.

iptables: A Packet's Possible Paths
Figure 16.1: iptables: A Packet's Possible Paths

16.2 Masquerading Basics

Masquerading is the Linux-specific form of NAT (network address translation) and can be used to connect a small LAN with the Internet. LAN hosts use IP addresses from the private range (see Book “Reference”, Chapter 13 “Basic Networking”, Section 13.1.2 “Netmasks and Routing”) and on the Internet official IP addresses are used. To be able to connect to the Internet, a LAN host's private address is translated to an official one. This is done on the router, which acts as the gateway between the LAN and the Internet. The underlying principle is a simple one: The router has more than one network interface, typically a network card and a separate interface connecting with the Internet. While the latter links the router with the outside world, one or several others link it with the LAN hosts. With these hosts in the local network connected to the network card (such as eth0) of the router, they can send any packets not destined for the local network to their default gateway or router.

Important
Important: Using the Correct Network Mask

When configuring your network, make sure both the broadcast address and the netmask are the same for all local hosts. Failing to do so prevents packets from being routed properly.

As mentioned, whenever one of the LAN hosts sends a packet destined for an Internet address, it goes to the default router. However, the router must be configured before it can forward such packets. For security reasons, this is not enabled in a default installation. To enable it, add the line net.ipv4.ip_forward = 1 in the file /etc/sysctl.conf. Alternatively do this via YaST, for example by calling yast routing ip-forwarding on.

The target host of the connection can see your router, but knows nothing about the host in your internal network where the packets originated. This is why the technique is called masquerading. Because of the address translation, the router is the first destination of any reply packets. The router must identify these incoming packets and translate their target addresses, so packets can be forwarded to the correct host in the local network.

With the routing of inbound traffic depending on the masquerading table, there is no way to open a connection to an internal host from the outside. For such a connection, there would be no entry in the table. In addition, any connection already established has a status entry assigned to it in the table, so the entry cannot be used by another connection.

As a consequence of all this, you might experience some problems with several application protocols, such as ICQ, cucme, IRC (DCC, CTCP), and FTP (in PORT mode). Web browsers, the standard FTP program, and many other programs use the PASV mode. This passive mode is much less problematic as far as packet filtering and masquerading are concerned.

16.3 Firewalling Basics

Firewall is probably the term most widely used to describe a mechanism that controls the data flow between networks. Strictly speaking, the mechanism described in this section is called a packet filter. A packet filter regulates the data flow according to certain criteria, such as protocols, ports, and IP addresses. This allows you to block packets that, according to their addresses, are not supposed to reach your network. To allow public access to your Web server, for example, explicitly open the corresponding port. However, a packet filter does not scan the contents of packets with legitimate addresses, such as those directed to your Web server. For example, if incoming packets were intended to compromise a CGI program on your Web server, the packet filter would still let them through.

A more effective but more complex mechanism is the combination of several types of systems, such as a packet filter interacting with an application gateway or proxy. In this case, the packet filter rejects any packets destined for disabled ports. Only packets directed to the application gateway are accepted. This gateway or proxy pretends to be the actual client of the server. In a sense, such a proxy could be considered a masquerading host on the protocol level used by the application. One example for such a proxy is Squid, an HTTP and FTP proxy server. To use Squid, the browser must be configured to communicate via the proxy. Any HTTP pages or FTP files requested are served from the proxy cache and objects not found in the cache are fetched from the Internet by the proxy.

The following section focuses on the packet filter that comes with openSUSE Leap. For further information about packet filtering and firewalling, read the Firewall HOWTO.

16.4 firewalld

firewalld is a daemon that maintains the system's iptables rules and offers a D-Bus interface for operating on them. It comes with a command line utility firewall-cmd and a graphical user interface firewall-config for interacting with it. Since firewalld is running in the background and provides a well defined interface it allows other applications to request changes to the iptables rules, for example to setup virtual machine networking.

firewalld implements different security zones. A number of predefined zones like internal or public exist. The administrator can define additional custom zones if desired. Each zone contains its own set of iptables rules. Each network interface is member of exactly one zone. Individual connections can also be assigned to a zone based on the source addresses.

Each zone represents a certain level of trust. For example the public zone is not trusted, because other computers in this network are not under your control (suitable for Internet or wireless hotspot connections). On the other hand the internal zone is used for networks that are under your control like a home or company network. By utilizing zones this way a host can offer different kinds of services to trusted networks and untrusted networks in a defined way.

For more information about the predefined zones and their meaning in firewalld refer to its manual at http://www.firewalld.org/documentation/zone/predefined-zones.html.

Note
Note: No Zone Assigned Behavior

The initial state for network interfaces is to be assigned to no zone at all. In this case the network interface will be implicitly handled in the default zone which can be determined by calling firewall-cmd --get-default-zone. If not configured otherwise, the default zone is the public zone.

The firewalld packet filtering model allows any outgoing connections to pass. Outgoing connections are connections that are actively established by the local host. Incoming connections that are established by remote hosts are blocked, if the respective service is not allowed in the zone in question. Therefore, each of the interfaces with incoming traffic must be placed into a suitable zone to allow for the desired services to be accessible. For each of the zones, define the services or protocols you need.

An important concept of firewalld is the distinction between two separate configurations, the runtime and the permanent configuration. The runtime configuration represents the currently active rules, while the permanent configuration represents the saved rules that will be applied when restarting firewalld. This allows to add temporary rules that will be discarded after restart of firewalld, or to experiment with new rules while being able to revert back to the original state. When you are changing the configuration you need to be aware of which configuration you're editing. How this is done is discussed in Section 16.4.1.2, “Runtime versus Permanent Configuration”.

If you want to perform the firewalld configuration using the graphical user interface firewall-config then refer to its documentation in http://www.firewalld.org/documentation/utilities/firewall-config.html. In the following section we will be looking at how to perform typical firewalld configuration tasks using firewall-cmd on the command line.

16.4.1 Configuring the Firewall on the Command Line

16.4.1.1 Firewall Startup

firewalld will be installed and enabled by default. It is a regular systemd service that can be configured via systemctl or the YaST Services Manager.

Important
Important: Automatic Firewall Configuration

After the installation, YaST automatically starts firewalld and leaves all interfaces in the default public zone. If a server application is configured and activated on the system, YaST can adjust the firewall rules via the options Open Ports on Selected Interface in Firewall or Open Ports on Firewall in the server configuration modules. Some server module dialogs include a Firewall Details button for activating additional services and ports.

16.4.1.2 Runtime versus Permanent Configuration

By default all firewall-cmd commands operate on the runtime configuration. You can apply most operations to the permanent configuration only by adding the --permanent parameter. When doing so the change will only affect the permanent configuration but will not be effective immediatly in the runtime configuration. There is currently no way to add a rule to both runtime and permanent configuration in a single invocation. To achieve this you can apply all necessary changes to the runtime configuration and when all is working as expected issue the following command:

root # firewall-cmd --runtime-to-permanent

This will write all current runtime rules into the permanent configuration. Any temporary modifications you or other programs may have made to the firewall in other contexts are made permanent this way. If you're unsure about this you can also take the opposite approach to be on the safe side: Add new rules to the permanent configuration and reload firewalld to make them active.

Note
Note

Some configuration items like the default zone are shared by both the runtime and permanent configuration. Changing them will reflect in both configurations at once.

To revert the runtime configuration to the permanent configuration and thereby discard any temporary changes there exist two possibilities, either via the firewalld command line interface or via systemd:

root # firewall-cmd --reload
root # systemctl reload firewalld

For brevity the examples in the following sections will always operate on the runtime configuration, if applicable. Adjust them accordingly if you want to make them permanent.

16.4.1.3 Assignment of Interfaces to Zones

You can list all network interfaces currently assigned to a zone like this:

root # firewall-cmd --zone=public --list-interfaces
eth0

Similarly you can query which zone a specific interface is assigned to:

root # firewall-cmd --get-zone-of-interface=eth0
public

The following command lines assign an interface to a zone. The variant using --add-interface will only work if eth0 is not already assigned to another zone. The variant using --change-interface will always work, removing eth0 from its current zone if necessary:

root # firewall-cmd --zone=internal --add-interface=eth0
root # firewall-cmd --zone=internal --change-interface=eth0

Any operations without an explicit --zone argument will impliticly operate on the default zone. This pair of commands can be used for getting and setting the default zone assignment:

root # firewall-cmd --get-default-zone
dmz
root # firewall-cmd --set-default-zone=public
Important
Important

Any network interfaces not explicitly assigned to a zone will be automatically part of the default zone. Changing the default zone will reassign all those network interfaces immediately for the permanent and runtime configurations. You should never use a trusted zone like internal as the default zone to avoid unexpected exposure to threats. For example hotplugged network interfaces like USB ethernet interfaces would automatically become part of the trusted zone in such cases.

Also note that interfaces that are not explicitly part of any zone will not appear in the zone interface list. There is currently no command to list unassigned interfaces. Due to this it is best to avoid unassigned network interfaces during regular operation.

16.4.1.4 Making Network Services Accessible

firewalld has a concept of services. A service consists of definitions of ports and protocols. These definitions logically belong together in the context of a given network service like a web or mail server protocol. The following commands can be used to get information about predefined services and their details:

root # firewall-cmd --get-services
[...] dhcp dhcpv6 dhcpv6-client dns docker-registry [...]
root # firewall-cmd --info-service dhcp
dhcp
  ports: 67/udp
  protocols:
  source-ports:
  modules:
  destination:

These service definitions can be used for easily making the associated network functionality accessible in a zone. This command line will open the http web server port in the internal zone, for example:

root # firewall-cmd --add-service=http --zone=internal

The removal of a service from a zone is performed using the counterpart command --remove-service. You can also define custom services using the --new-service sub-command. Refer to http://www.firewalld.org/documentation/howto/add-a-service.html for more details on how to do this.

If you just want to open a single port by number you can use the following approach. This will open TCP port 8000 in the internal zone:

root # firewall-cmd --add-port=8000/tcp --zone=internal

For removal use the counterpart command --remove-port.

Tip
Tip: Temporarily Opening a Service or Port

firewalld supports a --timeout parameter that allows to open a service or port for a limited time duration. This can be helpful for quick testing and makes sure that closing the service or port will not be forgotten. To allow the imap service in the internal zone for 5 minutes, you would call

root # firewall-cmd --add-service=imap --zone=internal --timeout=5m

16.4.1.5 Lockdown Mode

firewalld offers a lockdown mode that prevents changes to the firewall rules while being active. Since applications can automatically change the firewall rules via the D-Bus interface and depending on the PolicyKit rules regular users may be able to do the same it can be helpful to prevent changes in some situations. You can find more information about this in https://fedoraproject.org/wiki/Features/FirewalldLockdown.

It is important to understand that the lockdown mode feature provides no real security but merely protection against accidental or benign attempts to change the firewall. The way the lockdown mode is currently implemented in firewalld provides no security against malicious intent as is pointed out in http://seclists.org/oss-sec/2017/q3/139.

16.4.1.6 Adding Custom iptables Rules

firewalld claims exclusive control over the host's netfilter rules. You should never modify firewall rules using other tools like iptables. Doing so could confuse firewalld and break security or functionality.

If you need to add custom firewall rules that aren't covered by firewalld features then there are two ways to do so. To directly pass raw iptables syntax you can use the --direct option. It expects the table, chain and priority as initial arguments and the rest of the command line is passed as is to iptables. The following example adds a connection tracking rule for the forwarding filter table:

root # firewall-cmd  --direct --add-rule ipv4 filter FORWARD 0 -i eth0 -o eth1 \
    -p tcp --dport 80 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT

Additionally, firewalld implements so called rich rules, an extended syntax for specifying iptables rules in an easier way. You can find the syntax specification in http://www.firewalld.org/documentation/man-pages/firewalld.richlanguage.html. the following example drops all IPv4 packets originating from a certain source address:

root # firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" \
    source address="192.168.2.4" drop'

16.4.1.7 Routing, Forwarding and Masquerading

firewalld is not designed to run as a fully fledged router. The basic functionality for typical home router setups is available. For a corporate production router you should not use firewalld, however, but use dedicated router and firewall devices instead. The following provides just a few pointers what to look for to utilize routing in firewalld:

  • First of all IP forwarding needs to be enabled as outlined in Section 16.2, “Masquerading Basics”.

  • To enable IPv4 masquerading, for example in the internal zone, issue the following command

    root # firewall-cmd --zone=internal --add-masquerade
  • firewalld can also enable port forwarding. The following command will forward local TCP connections on port 80 to another host:

    root # firewall-cmd --zone=public \
        --add-forward-port=port=80:proto=tcp:toport=80:toaddr=192.168.1.10

16.4.2 Accessing Services Listening on Dynamic Ports

Some network services do not listen on predefined port numbers. Instead they operate based on the portmapper or rpcbind protocol. We will use the term rpcbind from here on. When one of these services starts, it chooses a random local port and talks to rpcbind to make the port number known. rpcbind itself is listening on a well known port. Remote systems can then query rpcbind about the network services it knows about and on which ports they are listening. Not many programs use this approach any more today. Popular examples are Network Information Services (NIS; ypserv and ypbind) and the Network File System (NFS) version 3.

Note
Note: About NFSv4

The newer NFSv4 only requires the single well known TCP port 2049 any more. For protocol version 4.0 the kernel parameter fs.nfs.nfs_callback_tcpport may need to be set to a static port (see Example 16.1, “callback port configuration for the nfs kernel module in /etc/modprobe.d/60-nfs.conf). Starting with protocol version 4.1 this setting has also become unnecessary.

The dynamic nature of the rpcbind protocol makes it difficult to make the affected services behind the firewall accessible. firewalld does not support these services by itself. For manual configuration, see Section 16.4.2.1, “Configuring Static Ports”. Alternatively, openSUSE Leap provides a helper script. For details, see Section 16.4.2.2, “Using firewall-rpcbind-helper for Configuring Static Ports”.

16.4.2.1 Configuring Static Ports

One possibility is to configure all involved network services to use fixed port numbers. Once this is done, the fixed ports can be opened in firewalld and everything should work. The actual port numbers used are at your discretion but should not clash with any well known port numbers assigned to other services. See Table 16.1, “Important Sysconfig Variables for Static Port Configuration” for a list of the available configuration items for NIS and NFSv3 services. Note that depending on your actual NIS or NFS configuration not all of these ports may be required for your setup.

Table 16.1: Important Sysconfig Variables for Static Port Configuration

File Path

Variable Name

Example Value

/etc/sysconfig/nfs MOUNTD_PORT 21001
STATD_PORT 21002
LOCKD_TCPPORT 21003
LOCKD_UDPPORT 21003
RQUOTAD_PORT 21004
/etc/sysconfig/ypbind YPBIND_OPTIONS -p 24500
/etc/sysconfig/ypserv YPXFRD_ARGS -p 24501
YPSERV_ARGS -p 24502
YPPASSWDD_ARGS --port 24503

You will need to restart any related services that are affected by these static port configurations for the changes to take effect. You can see the currently assigned rpcbind ports by using the command rpcinfo -p. On success only the statically configured ports should show up there any more.

Apart from the port configuration for network services running in userspace there are also ports that are used by the Linux kernel directly when it comes to NFS. One of these ports is the nfs_callback_tcpport. It is only required for the NFS protocol older than version 4.1. There is a sysctl named fs.nfs.nfs_callback_tcpport to configure this port. This sysctl node only appears dynamically when NFS mounts are active. Therefore it is best to configure the port via kernel module parameters. This can be achieved by creating a file like shown in Example 16.1, “callback port configuration for the nfs kernel module in /etc/modprobe.d/60-nfs.conf.

Example 16.1: callback port configuration for the nfs kernel module in /etc/modprobe.d/60-nfs.conf
options nfs callback_tcpport=21005

To make this change effective it is easiest to reboot the machine. Otherwise all NFS services need to be stopped and the nfs kernel module needs to be reloaded. To verify the active NFS callback port check the output of cat /sys/module/nfs/parameters/callback_tcpport.

For easy handling of the now statically configured RPC ports it is useful to create a new firewalld service definition. This service definition will group all related ports and for example makes it easy to make them accessible in a specific zone. In Example 16.2, “Commands to Define a new firewalld RPC Service for NFS” this is done for the NFS ports as they have been configured in the accompanying examples.

Example 16.2: Commands to Define a new firewalld RPC Service for NFS
root # firewall-cmd --permanent --new-service=nfs-rpc
root # firewall-cmd --permanent --service=nfs-rpc --set-description="NFS related, statically configured RPC ports"
# add UDP and TCP ports for the given sequence
root # for port in 21001 21002 21003 21004; do
    firewall-cmd --permanent --service=nfs-rpc --add-port ${port}/udp --add-port ${port}/tcp
done
# the callback port is TCP only
root # firewall-cmd --permanent --service=nfs-rpc --add-port 21005/tcp

# show the complete definition of the new custom service
root # firewall-cmd --info-service=nfs-rpc --permanent -v
nfs-rpc
  summary:
  description: NFS and related, statically configured RPC ports
  ports: 4711/tcp 21001/udp 21001/tcp 21002/udp 21002/tcp 21003/udp 21003/tcp 21004/udp 21004/tcp
  protocols:
  source-ports:
  modules:
  destination:

# reload firewalld to make the new service definition available
root # firewall-cmd --reload

# the new service definition can now be used to open the ports e.g. in the internal zone
root # firewall-cmd --add-service=nfs-rpc --zone=internal

16.4.2.2 Using firewall-rpcbind-helper for Configuring Static Ports

The steps to configure static ports as shown in the previous section can be simplified by using the SUSE helper tool firewall-rpc-helper.py. Install it with zypper in firewalld-rpcbind-helper.

The tool allows interactive configuration of the service patterns discussed in the previous section. It can also display current port assignments and can be used for scripting. For details, see firewall-rpc-helper.py --help.

16.5 For More Information

The most up-to-date information and other documentation about firewalld package is found in /usr/share/doc/packages/firewalld. The home page of the netfilter and iptables project, http://www.netfilter.org, provides a large collection of documents about iptables in general in many languages.

Print this page