3

I'm trying to setup firewalld to restrict access to the CentOS7 server to specific IPs (192.168.10.5 and 167.165.100.22) both for incoming and outgoing traffic.

I have only one network interface, enp0s01.

I have switched the firewalld a custom zone that has 'ssh' service enabled.

firewall-cmd --zone=customlist --list-all
internal (active)
target: default
icmp-block-inversion: no
interfaces: enp0s01
sources:
services: ssh
ports:
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:

I tested with adding one IP address, for example,

firewall-cmd --permanent --zone=external --add-source=192.168.10.5

However, other IPs within the network could still access the server via ssh.

How can I restrict the access? I thought firewall blocks all traffic unless explicitly whitelisted by adding the source.

0

Background

In researching this it appears that you cannot restrict outgoing traffic using the basic firewalld commands. Several sources back this up:

Your only recourse is to make use of firewall-cmd --direct ... commands which do little more than facilitate iptables rules for you. Given this you have a choice of doing this through Firewalld or just doing this using whatever methods you may have employed previously when using iptables.

NOTE: direct rules will look something like this:

$ firewall-cmd --direct --remove-rule ipv4 filter OUTPUT 0 -d 74.125.136.99/32 -p tcp -m tcp --dport=80 -j DROP

Potential solution

If you can relax the requirement of disallowing the host from any outgoing communications, you can get most of what you want as follows using the basic firewall-cmd commands.

NOTE: In my example I have 3 nodes:

  • 192.168.56.101 - VM #1 - server with Firewalld rules
  • 192.168.56.102 - VM #2
  • 192.168.56.1 - my laptop
Firwalld commands:
$ firewall-cmd --permanent --zone=internal --add-source=192.168.56.101/32
$ firewall-cmd --permanent --zone=internal --add-source=192.168.56.1/32
$ firewall-cmd --permanent --zone=internal --add-port=8080/tcp
$ firewall-cmd --zone=public --set-target=DROP

With this set up I can access VM #1 from my laptop, but cannot from anywhere else, such as from VM #2.

default zone
$ firewall-cmd --get-default-zone
public
active zones
$ firewall-cmd --get-active-zones
internal
  sources: 192.168.56.101/32 192.168.56.1/32
public
  interfaces: eth0 eth1
public zone's setup
$ firewall-cmd --zone=public --list-all
public (active)
  target: DROP
  icmp-block-inversion: no
  interfaces: eth0 eth1
  sources:
  services: ssh dhcpv6-client
  ports:
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:
internal zone's setup
$ firewall-cmd --zone=internal --list-all
internal (active)
  target: default
  icmp-block-inversion: no
  interfaces:
  sources: 192.168.56.101/32 192.168.56.1/32
  services: ssh mdns samba-client dhcpv6-client
  ports: 8080/tcp
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:
public zone's default target
$ firewall-cmd --permanent --get-target
DROP

Testing

To test this setup, I'm going to make use of nc (ncat) to create a 'listener daemon' on port 8080 and use curl -v telnet://... commands to act as clients which will connect to these listeners.

NOTE: This is purely to illustrate that things are working as expected, and can be removed later on.

On VM #1:
$ nc -4 -l -p 8080 -k
Now on VM #2 notice we cannot connect:
$ timeout 1 curl -v telnet://192.168.56.101:8080
* About to connect() to 192.168.56.101 port 8080 (#0)
*   Trying 192.168.56.101...
$
While on laptop we can:
$ timeout 1 curl -v telnet://192.168.56.101:8080
* Rebuilt URL to: telnet://192.168.56.101:8080/
*   Trying 192.168.56.101...
* Connected to 192.168.56.101 (192.168.56.101) port 8080 (#0)
$

The only catch with this approach, is that the VM #1 node can still egress:

$ timeout 2 ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=63 time=26.4 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=63 time=25.6 ms
$

$ timeout 1 curl -v telnet://www.google.com:80
* About to connect() to www.google.com port 80 (#0)
*   Trying 216.58.217.164...
* Connected to www.google.com (216.58.217.164) port 80 (#0)
$

References

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.