Linux防火墙教程(二):nftables

参考自Arck Wiki Nftables

安装

首先安装 nftables:

1
2
3
4
# ubuntu
sudo apt install nftables
# Arch & Manjaro
sudo pacman -S nftables

防火墙配置

开启防火墙

启用并设置 nftables 防火墙开机自启。

1
2
sudo systemctl start nftables
sudo systemctl enable nftables

配置文件

nftables 默认从/etc/nftables.conf配置文件中加载规则。

将规则写入到文件中。

1
nft list ruleset > filename

手动加载文件中的规则。

1
nft -f filename

表管理

和 iptables 一样,nftables 也有表和链的概念。不过不同的是,nftables 默认没有加载任何表的配置,所有配置都需要用户自己创建。在创建表的时候需要指定家族,每个家族对应的 iptables 功能如下。如果没有指定家族,则默认使用 ip 家族,也就是 IPv4 的表。

nftables familyiptables utility
ipiptables
ip6ip6tables
inetiptables and ip6tables
arparptables
bridgeebtables

在使用 nftables 之前,自然需要先创建表。

1
nft add table family_type table_name

列出所有表。

1
nft list tables

删除表。

1
nft delete table family_type table_name

清空表。

1
nft flush table family_type table_name

列出一个表中的所有链。

1
nft list table family_type table_name

链管理

创建链。

1
nft add chain inet my_table my_tcp_chain

列出链。

1
nft list chain family_type table_name chain_name

编辑链。

1
nft chain family_type table_name chain_name '{ [ type chain_type hook hook_type device device_name priority priority_value ; policy policy_type ; ] }'

删除链。

1
nft delete chain family_type table_name chain_name

清空链。

1
nft flush chain family_type table_name chain_name

规则

向链中添加规则。

1
nft add rule family_type table_name chain_name handle handle_value statement

handle_value处插入规则,不指定则在末尾追加。

1
nft insert rule family_type table_name chain_name handle handle_value statement

规则的语句(statement)部分由匹配的表达式和要执行的结果组成,这点和 iptables 一样。以下是匹配参数的一个不完全列表,详情参考nft命令帮助。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
meta:
  oif <output interface INDEX>
  iif <input interface INDEX>
  oifname <output interface NAME>
  iifname <input interface NAME>

  (oif and iif accept string arguments and are converted to interface indexes)
  (oifname and iifname are more dynamic, but slower because of string matching)

icmp:
  type <icmp type>

icmpv6:
  type <icmpv6 type>

ip:
  protocol <protocol>
  daddr <destination address>
  saddr <source address>

ip6:
  daddr <destination address>
  saddr <source address>

tcp:
  dport <destination port>
  sport <source port>

udp:
  dport <destination port>
  sport <source port>

sctp:
  dport <destination port>
  sport <source port>

ct:
  state <new | established | related | invalid>

删除规则前需要知道句柄,然后才能删除。

1
2
nft --handle --numeric list chain inet my_table my_input
nft delete rule inet my_table my_input handle 10

也可以清空或者删除链。

1
2
3
nft flush table table_name
nft flush chain family_type table_name chain_name
nft delete rule family_type table_name chain_name

集合

集合以一堆花括号组成,可以容纳多个参数。匿名集合不能修改,只能整个添加和删除。

1
nft add rule ip6 filter input tcp dport {telnet, http, https} accept

命名集合可以动态修改其中的元素。例如有如下配置。

1
2
3
4
5
6
table ip sshguard {
       set attackers {
               type ipv4_addr
               flags interval
               elements = { 1.2.3.4 }
       }

然后就可以对 set 进行修改。

1
2
nft add element ip sshguard attackers { 5.6.7.8/32 }
nft delete element ip sshguard attackers { 1.2.3.4/32 }

原子重载

创建一个临时配置文件,在开头清空所有规则,然后将已有规则写入。这样每次用该文件导入的时候,就可以完美还原配置文件中的内容。

1
2
3
echo "flush ruleset" > /tmp/nftables
nft -s list ruleset >> /tmp/nftables
nft -f /tmp/nftables

示例配置

基本配置

通过命令行配置一个简单的防火墙。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# 清空规则
nft flush ruleset
# 创建过滤表
nft add table inet filter
# 创建链,默认状态启用
nft add chain inet filter input '{ type filter hook input priority 0; }'
nft add chain inet filter forward '{ type filter hook forward priority 0; }'
nft add chain inet filter output '{ type filter hook output priority 0; }'
# 禁用所有传入连接
nft chain inet filter input '{ policy drop ; }'
# 允许SSH连入
nft add rule inet filter input \
   tcp dport 22 \
   accept \
   comment \"Allow SSH\"

配置文件内容。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
table inet filter {
        chain input {
                type filter hook input priority filter; policy drop;
                tcp dport 22 accept comment "Allow SSH"
        }

        chain forward {
                type filter hook forward priority filter; policy accept;
        }

        chain output {
                type filter hook output priority filter; policy accept;
        }
}

限制速率

还可以限制一些连接的速率。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
table inet my_table {
 chain my_input {
  type filter hook input priority filter; policy drop;

  iif lo accept comment "Accept any localhost traffic"
  ct state invalid drop comment "Drop invalid connections"

  meta l4proto icmp icmp type echo-request limit rate over 10/second burst 4 packets drop comment "No ping floods"
  meta l4proto ipv6-icmp icmpv6 type echo-request limit rate over 10/second burst 4 packets drop comment "No ping floods"

  ct state established,related accept comment "Accept traffic originated from us"

  meta l4proto ipv6-icmp icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, echo-reply, parameter-problem, mld-listener-query, mld-listener-report, mld-listener-reduction, nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, ind-neighbor-solicit, ind-neighbor-advert, mld2-listener-report } accept comment "Accept ICMPv6"
  meta l4proto icmp icmp type { destination-unreachable, router-solicitation, router-advertisement, time-exceeded, parameter-problem } accept comment "Accept ICMP"
  ip protocol igmp accept comment "Accept IGMP"

  tcp dport ssh ct state new limit rate 15/minute accept comment "Avoid brute force on SSH"

 }

}

更加复杂的配置这里就不再列出了。

comments powered by Disqus
本站总访问量次,总访客数人,当前页面总访问量
Built with Hugo
主题 StackJimmy 设计