Firewalld - source IP not working

New to firewalld, and having an issue trying to emulate my old iptable ruleset.

Server has one network interface, which I usually only allow SSH in from certain IPs, I know I can do this with rich rules but have read that this is sub-optimal.

So, I created a new zone, ABCinternal, added a couple of source IPs that are allowed to SSH in, reloaded the firewall and IPs other than the ones listed can still SSH in - what am I missing here?

[root@rhel7-test zones]# firewall-cmd --zone=ABCinternal --list-all
ABCinternal (active)
  target: 
  icmp-block-inversion: no
  interfaces:
  sources: 192.168.1.10 192.168.1.99
  services: ssh
  ports: 
  protocols: 
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 

You probably have not removed the ssh service from the default zone

firewall-cmd --permanent --zone=public --remove-service=ssh
firewall-cmd --reload

ssh was in there

So ran the below and reloaded and it made no difference

firewall-cmd --permanent --zone=public --remove-service=ssh

I did change the default zone to ABCinternal...may that is causing the problem?

firewall-cmd -get-default-zone
ABCinternal

Hmm, can you check all active zones, if service ssh or port 22/tcp is present somewhere? You can do this by either running

firewall-cmd --get-active-zones

and then for each zone listed

firewall-cmd --zone=xxx --list-protocols
firewall-cmd --zone=xxx --list-services

or by inspecting all xml-Files in /etc/firewalld/zones

I have added the interface, it's also in defined /etc/sysconfig/network-scripts/ifcfg-ens192, thinking that might be the issue but it made no difference.

firewall-cmd --get-active-zones
ABCinternal
  interfaces: ens192
  sources: 192.168.1.10 192.168.1.99
firewall-cmd --zone=ABCinternal --list-protocols
firewall-cmd --zone=public --list-protocols
firewall-cmd --zone=internal --list-protocols
firewall-cmd --zone=drop --list-protocols
firewall-cmd --zone=trusted --list-protocols
firewall-cmd --zone=dmz --list-protocols
firewall-cmd --zone=home --list-protocols
firewall-cmd --zone=work --list-protocols
firewall-cmd --zone=external --list-protocols

The above produced no output

firewall-cmd --zone=ABCinternal --list-services
ssh
firewall-cmd --zone=public --list-services
dhcpv6-client
firewall-cmd --zone=internal --list-services
ssh mdns samba-client dhcpv6-client
firewall-cmd --zone=drop --list-services
no output
firewall-cmd --zone=trusted --list-services
no output
firewall-cmd --zone=dmz --list-services
dmz
firewall-cmd --zone=home --list-services
ssh mdns samba-client dhcpv6-client
firewall-cmd --zone=work --list-services
ssh dhcpv6-client
firewall-cmd --zone=external --list-services
ssh

Also /etc/firewalld/zones only has 2 zones

ABCinternal.xml
ABCinternal.xml.old
public.xml
public.xml.old

You should remove any interface attributes from the ABCinternal zone or every ssh-connect arriving on one of the listed interfaces will be accepted.

I can't see any active services but ssh in your listings (because ABCinternal is the only active zone and it only accepts ssh). But let's say this machine is a webserver then you have to allow http in zone public in order for this to work.

Currently, all I need is ssh, and only from those IPs, hence why I only have ssh listed under the ABCinternal zone.

Previously I have removed the interface from the ABCinternal zone, so it was as below, but it made no difference.

firewall-cmd --get-active-zones
ABCinternal
  interfaces: 
  sources: 192.168.1.10 192.168.1.99

As I see it, I have a single zone configured, ABCinternal, that is active, and should only allow the 2 source IPs listed to ssh in, but it allows any IP to ssh in. I'm obviously not "getting" something but not sure what!

I got this going, the only way I got it to work was by adding rich rules.

First I added the rich rules

 firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.10" service name="ssh" accept'
 firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.99" service name="ssh" accept'

Then I removed the ssh service from the zone, which is the part that got me, seems counter intuiative.

 firewall-cmd --permanent zone=ABCinternal --remove-service=ssh 

Here is the /etc/firewalld/ABCinternal.xml file BEFORE I make the changes

<?xml version="1.0" encoding="utf-8"?>
<zone>
  <short>ABCinternal</short>
  <description>ABCinternal - internal trusted networks</description>
  <source address="192.168.1.10"/>
  <source address="192.168.1.99"/>
  <service name="ssh"/>
</zone>

And now after

<?xml version="1.0" encoding="utf-8"?>
<zone>
  <short>ABCinternal</short>
  <description>ABCinternal - internal trusted networks</description>
  <rule family="ipv4">
    <source address="192.168.1.10"/>
    <service name="ssh"/>
    <accept/>
  </rule>
  <rule family="ipv4">
    <source address="192.168.1.99"/>
    <service name="ssh"/>
    <accept/>
  </rule>
</zone>

I may use ipset if the list grows.

1 Like

One thing I now find odd though, is when I use

 firewall-cmd --zone=ABCinternal --list-services
no output

It doesn't list any services even though they are there, so the command doesn't list rich rules, this seems somewhat confusing - I now have to use

  firewall-cmd --zone=ABCinternal --list-all
ABCinternal (active)
  target: default
  icmp-block-inversion: no
  interfaces: ens192
  sources: 
  services:
  ports: 
  protocols: 
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 
	rule family="ipv4" source address="192.168.1.10" service name="ssh" accept
	rule family="ipv4" source address="1192.168.1.99" service name="ssh" accept