firewalld

最後更新: 2023-11-27

介紹

- zones - to define the trust level of network connections(source ip) or interfaces

* If firewalld gets started after the network is already up, the connections are not bound to a zone

- D-BUS interface - for firewall configuration of services and applications

- Command line - client for the user

目錄

 


安裝

 

yum install firewalld

systemctl start firewalld

# 當 sure 所有 rule 無問題才好 "enable", 否則 reboot 後也不能自救

systemctl enable firewalld

Opts:

-h, --help

# foreground process

--nofork

Check status

service firewalld status

stop:

Redirecting to /bin/systemctl status  firewalld.service
firewalld.service - firewalld - dynamic firewall daemon
   Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled)
   Active: inactive (dead)

start:

Redirecting to /bin/systemctl status  firewalld.service
firewalld.service - firewalld - dynamic firewall daemon
   Loaded: loaded (/usr/lib/systemd/system/firewalld.service; enabled)
   Active: active (running) since Wed 2015-01-14 00:12:28 EST; 22h ago
 Main PID: 31670 (firewalld)
   CGroup: /system.slice/firewalld.service
           └─31670 /usr/bin/python -Es /usr/sbin/firewalld --nofork --nopid

Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.

 


firewall-cmd

 

Check version

firewall-cmd --version

0.3.9

Check status

firewall-cmd --state

running

查看

firewall-cmd --get-services [--permanent]

amanda-client bacula bacula-client dhcp dhcpv6 dhcpv6-client dns ftp 
high-availability http https imaps ipp ipp-client ipsec kerberos kpasswd 
ldap ldaps libvirt libvirt-tls mdns mountd ms-wbt mysql nfs ntp openvpn pmcd 
pmproxy pmwebapi pmwebapis pop3s postgresql proxy-dhcp radius rpc-bind samba 
samba-client smtp ssh telnet tftp tftp-client transmission-client vnc-server wbem-https

firewall-cmd --list-all [--permanent] [--zone=public]

public (default, active)
  interfaces: eth0
  sources:
  services: dhcpv6-client ssh
  ports:
  masquerade: no
  forward-ports:
  icmp-blocks:
  rich rules:

其他類似 cmd 有

  • --list-ports
  • --list-services
  • --list-rich-rules
  • --list-interfaces    List interfaces that are bound to a zone [P] [Z]
  • --list-sources       List sources that are bound to a zone [P] [Z]
  • .......................

 * "--list-all" 係不會顯示 direct rule

 * "--list-all" default 只會顯示 public zone

P.S.

firewall-cmd --get-active-zone

internal
  interfaces: ens224
public
  interfaces: ens192

firewall-cmd --list-all --zone=internal

Remark

If NetworkManager is not used, there are some limitations:

* firewalld will not get notified about network device renames.

* Manually created interfaces are not bound to a zone.

* Please add them to a zone with

/bin/systemctl stop  NetworkManager.service

firewall-cmd --zone=zone --add-interface=interface

 * 一個 interface 只跟一個 zone !!

 


Temporary 與 Permanent Rule

 

Runtime configuration = temporary

actual active configuration and is not permanent. (reload/restart of the service)

Temporary Rule:

# --remove-service=http

firewall-cmd --zone=internal --add-port=443/tcp

Make the new settings persistent:

firewall-cmd --runtime-to-permanent

P.S.

在 cron job 上用 "/usr/sbin/iptables -F" 是無用的, 定期行亦 login 唔返入去

 


Zone

 

生效次序

  1. source already bound to a zone
  2. interface
  3. default zone

 * an interface cannot be assigned to more than one zone.

 * In its default configuration, firewalld pairs all interfaces with the public zone

 * A source cannot be assigned to multiple zones.

zone 的設定

length of zone_name is currently limited to 17 chars

# Default 都有好多 zone

firewall-cmd --get-zones

block dmz drop external home internal public trusted work

firewall-cmd --list-all-zones

..............

block
  target: %%REJECT%%
  icmp-block-inversion: no
  interfaces:
  sources:
  services:
  ports:
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

..............

public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0
  sources:
  services: dhcpv6-client ssh
  ports: 3260/tcp
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

..............

trusted
  target: ACCEPT
  icmp-block-inversion: no
  interfaces:
  sources:
  services:
  ports:
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

..............

firewall-cmd --get-active-zones

public
  interfaces: eno16777736

# 加了 source ip 才 active
trusted
  sources: 192.168.88.0/24

firewall-cmd --get-default-zone

# 所有沒有指定 "--zone=???" 的 Rule 都是在這個 zone

public

設定 default zone

# "firewall-cmd --state" 是 running 時才可設定

firewall-cmd --set-default-zone=public

Interface with zone

A zone can be bound to a network interface (see above) and/or to a network addressing (called here a source).

# 某 zone 有什麼 interface

firewall-cmd --list-interfaces

firewall-cmd --zone=public --list-interfaces

eth0

# 某 nic 是屬於那個 zone

firewall-cmd --get-zone-of-interface=eth0

public

加一 IP 入某 Zone

# Add

# Block an IP

firewall-cmd --zone=drop --add-source=n.n.n.n

Notes

如果要中止已建立的連線, 就要行

conntrack -D -s n.n.n.n

# Checking

firewall-cmd --zone=drop --list-all

Add / Remove Interface to a zone

# Remove interface from a zone

firewall-cmd --zone=public --remove-interface=virbr0 --permanent

msg

The interface is under control of NetworkManager and already bound to the default zone
The interface is under control of NetworkManager, setting zone to default.

 * 可以不理此 msg, 因為所有 Interface default 在 public Zone

# Add interface to a zone

firewall-cmd --zone=internal --add-interface=virbr0 --permanent

# Apply & Checking

firewall-cmd --reload

success

firewall-cmd --get-active-zone

internal
  interfaces: lxcbr0
public
  interfaces: ens4

 


Service

 

查看現成的 Service

firewall-cmd --get-services [--permanent]

ls -1 /usr/lib/firewalld/services

自定的 Service

ls -1 /etc/firewalld/services

service 的 xml file

myftp.xml

<?xml version="1.0" encoding="utf-8"?>
<service>
  <short>ftp</short>
  <description>PASV FTP Service</description>
  <port protocol="tcp" port="21"/>
  <port protocol="tcp" port="9000-9049"/>
</service>

Notes

#1. short = short description (是非必要的)

firewall-cmd --service=myftp --permanent --get-short

#2. description (是非必要的)

firewall-cmd --service=myftp --permanent --get-description

i.e. 自定 ftp service

建立 /etc/firewalld/services/myftp.xml

<?xml version="1.0" encoding="utf-8"?>
...

 * 檔名只可以是 alphanumeric, '_' 及 '-'

firewall-cmd --reload

查看 Service 的 Info

firewall-cmd --info-service=myftp [--permanent]

myftp                               # 檔案名
  ports: 21/tcp 9000-9049/tcp
  protocols:
  source-ports:
  modules:
  destination:
  includes:
  helpers:

找出 service 檔的位置

firewall-cmd --path-service=myftp --permanent   # 必須加上 "--permanent"

/etc/firewalld/services/myftp.xml

 

加 service

firewall-cmd --add-service=myftp --permanent

firewall-cmd --reload

刪除 service: --remove-service

firewall-cmd --remove-service=myftp --permanent

firewall-cmd --reload

P.S.

# 同時刪除多個 Services (多項的 "--remove-service")

firewall-cmd --zone=internal --permanent --remove-service={cockpit,dhcpv6-client,mdns,samba-client,ssh}

check-config

--check-config

Run checks on the permanent configuration. This includes XML validity and semantics.

firewall-cmd --check-config

success

 


Open Port

 

"--add-port" 與 "--remove-port"

firewall-cmd --zone=public --add-port=22/tcp --permanent

firewall-cmd --zone=zone --remove-port=portid[-portid]/protocol --permanent

firewall-cmd --remove-port=80/tcp

Port value

port=<port>[-<port>]

protocol="tcp|udp"

short - Is an optional start and end tag and is used to give a zone a more readable name.

interface - Is an optional empty-element tag and can be used several times. It can be used to bind an interface to a zone.

查看 status

systemctl status firewalld

firewalld.service - firewalld - dynamic firewall daemon
   Loaded: loaded (/usr/lib/systemd/system/firewalld.service; enabled)
   Active: active (running) since Mon 2015-01-12 21:46:47 EST; 49min ago
 Main PID: 597 (firewalld)
   CGroup: /system.slice/firewalld.service
           └─597 /usr/bin/python -Es /usr/sbin/firewalld --nofork --nopid

Jan 12 21:46:47 localhost.localdomain systemd[1]: Started firewalld - dynamic firewall daemon.
Jan 12 21:53:13 localhost.localdomain systemd[1]: Started firewalld - dynamic firewall daemon.
Jan 12 22:32:44 localhost.localdomain firewalld[597]: 2015-01-12 22:32:44 
ERROR: PARSE_ERROR: Unexpected element source
Jan 12 22:33:13 localhost.localdomain firewalld[597]: 2015-01-12 22:33:13 
ERROR: Failed to load service file '/etc/firewalld/services/mysql.xml': PARSE_ERROR: Unexp...ent source
Hint: Some lines were ellipsized, use -l to show in full.

# rich-rule

Is an optional element tag and can be used several times to have more than one rich language rule entry.

<rule [invert="ipv4|ipv6"]/>
  <source address="address[/mask]" [invert="bool"]/>
  [ <log [prefix="prefixtext"] [level="emerg|alert|crit|err|warn|notice|info|debug"]/> [<limit value="rate/duration"/>] </log> ]
  [ <audit> [<limit value="rate/duration"/>] </audit> ]
  <accept/> | <reject [type="rejecttype"]/> | <drop/>
</rule>

target="ACCEPT|REJECT|DROP"

The ACCEPT target is used in the trusted zone, every packet will be accepted.

The REJECT target is used in the block zone, every packet will be rejected with the default firewalld reject type.

The DROP target is used in the drop zone, every packet will be dropped.

The default

target is {chain}_ZONE_{zone} and will be used if the target is not specified.

If other than the default target is used, all settings except interface and source are ignored,

because the first rule created in firewall for this zone is 'jump to target'.

Example:

allow an ip range to port

* 要一句過, 唔用得 "/"

firewall-cmd --permanent --zone=public \
--add-rich-rule='rule family="ipv4" source address="x.x.x.x/24" port protocol="tcp" port="3306" accept'

allow an ip to a service

firewall-cmd --permanent --zone=public \
--add-rich-rule='rule family="ipv4" source address="x.x.x.x" service name="rsync" accept'

source-port

firewall-cmd --add-rich-rule='rule family="ipv4" source-port port="12345" protocol="tcp" drop'

# remove rich-rule:

firewall-cmd [--zone=zone] --remove-rich-rule='rule'

i.e.

firewall-cmd  --add-rich-rule='rule family="ipv4" source address="x.x.x.x" port port="7" protocol="tcp"  accept'

firewall-cmd --remove-rich-rule='rule family="ipv4" source address="x.x.x.x" port port="7" protocol="tcp"  accept'

firewall-cmd --list-all

 


Rich Rule Structure

 

rule [family="rule family"]
    [ source [NOT] [address="address"] [mac="mac-address"] [ipset="ipset"] ]
    [ destination [NOT] address="address" ]
    [ element ]
    [ log [prefix="prefix text"] [level="log level"] [limit value="rate/duration"] ]
    [ audit ]
    [ action ]

 


ACL: Allow ALL from an IP

 

# By rich rule

firewall-cmd --add-rich-rule='rule family="ipv4" source address="x.x.x.x" accept'

# By create a new zone

# FirewallD zones are defined by source addresses and by interfaces

# "--new-zone" 一定要 "--permanent"

i.e "work" zone rules will apply to the particular subnet.

firewall-cmd --new-zone=MyOffice --permanent

firewall-cmd --zone=MyOffice --add-source=192.168.123.200/32 --permanent

firewall-cmd --zone=MyOffice --add-port=2222/tcp --permanent

# Add IP to trusted zone

trusted zone

# Checking

firewall-cmd --get-active-zones

原本

public
  interfaces: eth0

新:

public
  interfaces: eth0
MyOffice
  sources: 192.168.123.200/32

 


Trusted Zone

 

firewall-cmd --permanent --zone=trusted --add-source=192.168.2.0/24

firewall-cmd --permanent --zone=trusted --list-sources

# –remove-source

# –change-source

 


Complete Reload

 

# To reload the firewall and interrupt user connections, that is to say, to discard state information

firewall-cmd --complete-reload

 


Masquerade

 

/etc/sysctl.conf

net.ipv4.ip_forward=1

sysctl -p

以前: (iptables 年代)

iptables -t nat -A POSTROUTING -s 192.168.123.0/24 -o eth0 -j MASQUERADE

現在: (firewall-cmd 年代)

# ens192 是第一張 NIC, 它本身在 public zone

firewall-cmd --zone=internal --add-interface=ens224 --permanent

firewall-cmd --zone=public --add-masquerade --permanent

firewall-cmd --reload

# Checking

cat /proc/sys/net/ipv4/ip_forward

1

firewall-cmd --get-active-zone

internal
  interfaces: ens224
public
  interfaces: ens192

firewall-cmd --zone=public --query-masquerade

yes

 


Port Forwarding(DNAT)

 

Add Port forwarding

# 2222/tcp -> 22/tcp

firewall-cmd --zone=public --permanent \
  --add-forward-port=port=2222:proto=tcp:toport=22:toaddr=192.168.200.11

Checking Port forwarding

firewall-cmd --list-all

...
  forward-ports:
        port=2222:proto=tcp:toport=22:toaddr=192.168.200.11
...

Remark

iptables-save | grep 2222

-A PRE_public_allow -p tcp -m tcp --dport 2222 -j MARK --set-xmark 0x64/0xffffffff

iptables-save | grep 0x64

-A PRE_public_allow -p tcp -m mark --mark 0x64 -j DNAT --to-destination 192.168.200.29:22
-A FWDI_public_allow -m conntrack --ctstate NEW,UNTRACKED -m mark --mark 0x64 -j ACCEPT

Remove Port Forwarding

firewall-cmd --zone=public --permanent \
  --remove-forward-port=port=2222:proto=tcp:toport=22:toaddr=192.168.200.11

限 Source IP 版本 Port Forwarding [Rich rule]

# 3307/tcp -> 3306/tcp

firewall-cmd --add-rich-rule='rule family=ipv4
source address=S.S.S.S
forward-port port=3307 protocol=tcp 
to-port=3306 to-addr=192.168.200.12'

Checking

firewall-cmd --list-rich-rules

多 Wan IP 版本 DNAT

# Set

D.D.D.D = Wan IP2

firewall-cmd --add-rich-rule='rule family=ipv4
destination address=D.D.D.D
forward-port port=3307 protocol=tcp 
to-port=3306 to-addr=192.168.200.22'

# Checking

firewall-cmd --list-all --permanent

Port Redirect

firewall-cmd --direct \
  --add-rule ipv4 nat PREROUTING 0 -p tcp --dport 1025:1030 -j REDIRECT --to-port 25

 * Priority 0 means add rule on top of the chain

Checking

firewall-cmd --direct --get-all-rules

ipv4 nat PREROUTING 0 -p tcp --dport 1025:1030 -j REDIRECT --to-port 25

P.S.

"REDIRECT" 的 "--to-port" 只會去本機的第一粒 IP (Sub IP 無效)

i.e.

postfix-1    10.0.0.11:1025~1030 --> 10.0.0.11:25
postfix-2    10.0.0.12:1025~1030 -/
postfix-3    10.0.0.13:1025~1030 /

 * 25/tcp 本身要 allow 先

 * "REDIRECT" 只有 "--to-port", 沒有 "-d"

加強版(比 "REDIRECT" 強) [Direct rule]

WAN_IP=10.0.0.12
firewall-cmd --direct --permanent \
  --add-rule ipv4 nat PREROUTING 0 \
  -p tcp -d $WAN_IP --dport 1025:1030 \
  -j DNAT --to-destination $WAN_IP:25

Checking

iptables -nL -t nat | grep 1025

firewall-cmd --direct --get-all-rules | grep 1025

 


Direct Rules

 

Which enables directly passing rules to iptables, ip6tables and ebtables.

It is intended for use by applications and not users.

CLI

firewall-cmd [--permanent] --direct ..

加減 Chain

firewall-cmd [--permanent] --direct --add-chain <ipv4|ipv6|eb> <table> <chain>

firewall-cmd [--permanent] --direct --remove-chain <ipv4|ipv6|eb> <table> <chain>

firewall-cmd [--permanent] --direct --query-chain <ipv4|ipv6|eb> <table> <chain>

firewall-cmd [--permanent] --direct --get-chains <ipv4|ipv6|eb> <table>

Chain

所有 chain 都會被自動改名

i.e.

  • INPUT -> INPUT_direct
  • FORWARD -> FORWARD_direct
  • OUTPUT -> OUTPUT_direct

Query & Get / Add / Remove Rule

Query & Get Rule

firewall-cmd [--permanent] --direct --get-all-rules

ie. firewall-cmd --direct --get-all-rules

ipv4 nat PREROUTING 0 -p tcp --dport 1025:1030 -j REDIRECT --to-port 587
ipv4 nat PREROUTING 0 -p tcp --dport 2525 -j REDIRECT --to-port 587

firewall-cmd [--permanent] --direct --get-rules <ipv4|ipv6|eb> <table> <chain>

i.e. firewall-cmd --direct --get-rules ipv4 nat PREROUTING

0 -p tcp --dport 1025:1030 -j REDIRECT --to-port 587
0 -p tcp --dport 2525 -j REDIRECT --to-port 587

firewall-cmd [--permanent] --direct --query-rule <ipv4|ipv6|eb> <table> <chain> <args>

Add Rule

firewall-cmd [--permanent] --direct --add-rule { ipv4 | ipv6 | eb } <table> <chain> <priority> <args>

i.e.

# ttl > 100 的 Outgoing block 了.

firewall-cmd --direct --add-rule ipv4 filter OUTPUT_direct 1 -o ens192 -p icmp -m ttl --ttl-gt 100 -j DROP

# 所有主機的 IP 都 port forward (443->192.168.200.29:443)

firewall-cmd --direct --permanent --add-rule \
  ipv4 filter FORWARD 1 -p tcp --dport 443 -j ACCEPT

# 指定某 IP port forward

firewall-cmd --direct --permanent --add-rule \
  ipv4 nat PREROUTING 1 -p tcp -d 10.10.10.11 --dport 443 -j DNAT \
  --to-destination 192.168.200.29:443

Remove Rule

firewall-cmd [--permanent] --direct --remove-rule { ipv4 | ipv6 | eb } <table> <chain> <args>

 * { ipv4 | ipv6 | eb } <table> <chain> <args> 不用 ""

 


Drop All Packets (Panic Mode)

 

# Result: no

firewall-cmd --query-panic

# All incoming and outgoing packets are dropped, active connections will expire.

firewall-cmd --panic-on

# Resume normal

firewall-cmd --panic-off

 


ICMP (ping)

 

firewall-cmd --get-icmptypes

... echo-request ... timestamp-request

firewall-cmd --add-icmp-block=timestamp-request --permanent

firewall-cmd --reload

# Checking

firewall-cmd --list-all

public (active)
  target: default
  icmp-block-inversion: no
  ...
  icmp-blocks: timestamp-request
  ...

 


Log denied

 

firewall-cmd --set-log-denied=all

firewall-cmd --get-log-denied

# log over limit (10 per minute)

firewall-cmd --permanent \
--add-rich-rule='rule family="ipv4" service name="ssh" log prefix="fw-ssh" level="info" limit value="10/m" accept'

Disable Log

/etc/firewalld/firewalld.conf

LogDenied=off

systemctl restart firewalld

 


Cheat List

 

Useful command

firewall-cmd --reload

firewall-cmd --list-all

firewall-cmd --add-service=mosh --permanent

firewall-cmd --zone=trusted --add-source=192.168.2.0/24 --permanent

CMD:

systemctl start firewalld

cp -a /usr/lib/firewalld/zones/public.xml /etc/firewalld/zones/

cp -a /usr/lib/firewalld/services/ssh.xml /etc/firewalld/services/

cp -a /usr/lib/firewalld/services/dhcpv6-client.xml  /etc/firewalld/services/

# 只看 rich rules

firewall-cmd --list-rich-rules

# Set zone interface

firewall-cmd --zone=public --add-interface=eth1 --permanent

# FTP

firewall-cmd --add-port=21/tcp --permanent

firewall-cmd --add-port=9001-9050/tcp --permanent

# Limit SSH

firewall-cmd --add-rich-rule='rule family="ipv4" source address="w.x.y.z" port protocol="tcp" port="22" accept' --permanent

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

Checking before auto start:

firewall-cmd --list-all --zone=public --permanent

Apply setting & auto start:

firewall-cmd --reload

systemctl enable firewalld

 


Comment

 

There is no option for firewalld rich rules yet,
 but direct rule can via '-m comment --comment "description"'.

i.e.

firewall-cmd --permanent \
--direct --add-rule ipv4 filter INPUT 0 -p tcp -m tcp -s 1.2.3.4 --dport=22 -j ACCEPT -m comment --comment "Office IP"

Checking

firewall-cmd --direct --get-all-rules

 


Doc

 

man 5 firewalld.icmptype — Describes XML configuration files for ICMP filtering.

man 5 firewalld.service — Describes XML configuration files for firewalld service.

man 5 firewalld.zone — Describes XML configuration files for firewalld zone configuration.

man 5 firewalld.richlanguage

https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/Security_Guide/sec-Using_Firewalls.html