网站内部链接:

ufw

介绍

ufw, Uncomplicated Firewall, 其在 Ubuntu 8.04 LTS 后的所有发行版中默认可用, 其图形用户界面为Gufw, 其是为轻量化配置 iptables 而开发的一款工具, 提供了更加友好的交互逻辑和简便的配置规则.

  1. ubuntu 上安装 ufw, 默认情况下其已经安装: apt-get install ufw
  2. 安装完成之后需要开启 ufw: ufw enable/disable

格式

命令的基本格式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 0. 显示规则并展示规则序号
ufw status numbered
# 1. 默认规则
default ARG
# 2. 日志等级和开关
logging LEVEL
# 3. 限制规则
limit ARGS
# 4. 删除规则
delete RULE/NUM
# 5. 插入规则
insert NUM RULE
# 6. 重启防火墙
reload
# 7. 重置防火墙
reset
# 8. 显示防火墙报告
show ARG

使用

  1. 查看当前 ufw 配置的规则, 每一行就是一个规则: ufw status

  2. 打开某个端口或者某个服务, 类似 firewalld, 其中ufw status输出的最后一列就是之前设置的端口以及服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 1. ftp, 此时设置开启21端口, 可以通过端口来开启
ufw allow ftp
# 设置vsftp一般使用如下设置
ufw allow 20,21,990/tcp
ufw allow 40000:50000/tcp

# 2. 允许所有协议的指定端口
ufw allow 53

# 3. 允许某个IP的所有端口
ufw allow from 192.168.1.100
# 允许从指定IP的指定端口到本机的指定端口
ufw allow proto tcp from 10.0.1.0/10 to 10.0.168.1 port 25

# 4. 禁止指定服务
ufw deny smtp

# 5. 删除上面配置的某个规则(ufw status的每一条记录)
ufw delete 20,21,990/tcp

# 6. 拒绝指定服务
ufw reject smtp
  1. 开启防火墙以及设置日志信息, 设置默认策略
1
2
3
4
5
6
7
8
# 1. 查看规则
ufw status
# 2. 转换日志
ufw logging on
ufw logging off
# 3. 默认策略
ufw default allow
ufw default deny

firewalld

介绍

firewalld 是 centos7 之后内置的一款动态防火墙管理器, 其通过”网络/防火墙”空间的方式, 为不同的网络连线或接口定义自身的信任等级. firewall-cmd则是 firewalld 的字符界面管理工具, 其支持动态更新, 新增防火墙 zone 概念, 相比原始的 iptables 配置, 其有如下两个好处:

  • 动态修改单条规则, 然而 iptables 更改某个规则之后需要全部刷新才能生效
  • 理解使用更加简便

其他相关工具还有firewall-config, 其是 firewalld 中可选的图形化配置工具, firewall-applet是 firewalld 中可选的状态栏小图标程序.

格式

firewalld 命令的基本格式: firewall-cmd options

1
2
3
4
5
6
7
8
# 1. 显示状态
--state
# 2. 不中断重新加载
--reload
# 3. 中断所有连接的加载
--complete-reload
# 4. 检查配置
--check-config

firewalld 命令的安装和启动配置:

1
2
3
4
5
6
7
8
# 1. 安装firewalld
yum install firewalld firewall-config
# 2. 启动, 停止, 自启动等
systemctl start firewalld # 启动
systemctl stop firewalld # 停止
systemctl enable firewalld # 启用自动启动
systemctl disable firewalld # 禁用自动启动
systemctl status firewalld # 或者 firewall-cmd --state 查看状态

使用

  1. 配置 firewalld
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
39
40
41
42
43
44
45
46
47
48
# a. 查看设置:
firewall-cmd --state # 显示状态
firewall-cmd --get-active-zones # 查看区域信息
firewall-cmd --get-zone-of-interface=eth0 # 查看指定接口所属区域
firewall-cmd --panic-on # 拒绝所有包
firewall-cmd --panic-off # 取消拒绝状态
firewall-cmd --query-panic # 查看是否拒绝

# b. 将接口添加到区域,默认接口都在public
firewall-cmd --zone=public --add-interface=eth0
# 永久生效再加上 --permanent 然后reload防火墙

# c. 设置默认接口区域,立即生效无需重启
firewall-cmd --set-default-zone=public

# d. 查看所有打开的端口:
firewall-cmd --zone=dmz --list-ports

# e. 加入一个端口到区域:
firewall-cmd --zone=dmz --add-port=8080/tcp
# 若要永久生效方法, 需要加载--permanent

# f. 打开一个服务,类似于将端口可视化,服务需要在配置文件中添加,/etc/firewalld 目录下有services文件夹
firewall-cmd --zone=work --add-service=smtp

# g. 移除服务
firewall-cmd --zone=work --remove-service=smtp

# 显示支持的区域列表
firewall-cmd --get-zones

# 设置为家庭区域
firewall-cmd --set-default-zone=home

# 查看当前区域
firewall-cmd --get-active-zones

# 设置当前区域的接口
firewall-cmd --get-zone-of-interface=enp03s

# 显示所有公共区域(public)
firewall-cmd --zone=public --list-all

# 临时修改网络接口(enp0s3)为内部区域(internal)
firewall-cmd --zone=internal --change-interface=enp03s

# 永久修改网络接口enp03s为内部区域(internal)
firewall-cmd --permanent --zone=internal --change-interface=enp03s
  1. 服务 service 管理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 显示服务列表
firewall-cmd --get-services

# 允许SSH服务通过
firewall-cmd --new-service=ssh

# 禁止SSH服务通过
firewall-cmd --delete-service=ssh

# 打开TCP的8080端口
firewall-cmd --enable ports=8080/tcp

# 临时允许Samba服务通过600秒
firewall-cmd --enable service=samba --timeout=600

# 显示当前服务
firewall-cmd --list-services

# 添加HTTP服务到内部区域(internal)
firewall-cmd --permanent --zone=internal --add-service=http
firewall-cmd --reload # 在不改变状态的条件下重新加载防火墙
  1. 端口管理
1
2
3
4
5
6
7
8
9
10
11
12
# 打开443/TCP端口
firewall-cmd --add-port=443/tcp

# 永久打开3690/TCP端口
firewall-cmd --permanent --add-port=3690/tcp

# 永久打开端口好像需要reload一下,临时打开好像不用,如果用了reload临时打开的端口就失效了
# 其它服务也可能是这样的,这个没有测试
firewall-cmd --reload

# 查看防火墙,添加的端口也可以看到
firewall-cmd --list-all
  1. 端口转发
1
2
3
firewall-cmd --add-forward-port=port=80:proto=tcp:toport=8080   # 将80端口的流量转发至8080
firewall-cmd --add-forward-port=port=80:proto=tcp:toaddr=192.168.0.1 # 将80端口的流量转发至192.168.0.1
firewall-cmd --add-forward-port=port=80:proto=tcp:toaddr=192.168.0.1:toport=8080 # 将80端口的流量转发至192.168.0.1的8080端口

ufw,firewalld,iptables 关系

iptables 和 ufw,firewalld

上文已经详细的介绍了 ufw 和 firewalld 的使用, 这里我们简单的梳理下ufw, firewalld, iptables三者的关系以及互相之间的影响. 首先, 从整个时间轴的角度来看待:

  • a. iptables 最先被使用, 其基于 netfilter 用于配置 centos 和 ubuntu 等基于 unix 内核的防火墙
  • b. centos7 内置 firewalld 以替代 iptables 作为新的防火墙管理工具, 当然后者仍然能够使用
  • c. ubuntu8.04LTS 后内置 ufw 作为新的防火墙管理工具

其次, 从功能角度考虑, ufw 和 firewall 都是对 iptables 的补充和完善, 但是这两者提供了更加友好和更加简单的命令配置为系统管理员提供更加简便快捷的防火墙配置操作, 当然, 这两者底层调用仍然是 iptables, 最终影响到 netfilter 内核.
下面我们通过实际情况来说明配置 ufw 或者 firewalld 是怎么影响到 iptables 的规则输出.

  1. firewalld 未启动, iptables 未配置任何规则时, 命令iptables -L的输出如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
# 1. 关闭firewalld
systemctl stop firewalld
# 2. 查看iptables规则
iptables -L
# 输入如下:
Chain INPUT (policy ACCEPT)
target prot opt source destination

Chain FORWARD (policy ACCEPT)
target prot opt source destination

Chain OUTPUT (policy ACCEPT)
target prot opt source destination

此时, 外部主机访问该服务器没有任何限制, 防火墙处于不设防的状态.

  1. firewalld 启动并设置某些规则时, 命令的输出如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 1. 启动firewalld并设置规则
systemctl start firewalld
firewall-cmd --list-ports
# 输出如下
3306/tcp 8000/tcp 80/tcp

# 2. 此时查看iptables
iptables -L
# 此时输出会多处很多新的iptables规则, 同时有一个public zone的规则信息:
Chain IN_public_allow (1 references)
target prot opt source destination
ACCEPT tcp -- anywhere anywhere tcp dpt:ssh ctstate NEW,UNTRACKED
ACCEPT tcp -- anywhere anywhere tcp dpt:mysql ctstate NEW,UNTRACKED
ACCEPT tcp -- anywhere anywhere tcp dpt:8000 ctstate NEW,UNTRACKED
ACCEPT tcp -- anywhere anywhere tcp dpt:http ctstate NEW,UNTRACKED

这里 mysql 就是 3306 端口, http 就是 80 端口, 说明通过 firewalld 配置防火墙规则最终也影响到了 iptables 规则.

  1. firewalld 默认未开启, 关闭 ufw, 此时 iptables 的输出类似上面的 1 测试输出
1
2
3
# 1. 关闭ufw
ufw disable
# 2. 此时查看iptables, 相比firewalld关闭之后的测试, 此时iptables输出内容较多, 但实际上都是allow规则
  1. firewalld 默认未开启, 启动 ufw 并设置规则, 此时 iptables 的输出发生变动, 产生新的防火墙规则策略
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 1. 启动ufw
ufw enable
ufw status
# 部分输出如下:
状态: 激活

至 动作 来自
- -- --
OpenSSH ALLOW Anywhere
20,21,990/tcp ALLOW Anywhere

# 2. 此时iptables的输出会携带如下值(990为ftps隐式端口)
ACCEPT tcp -- anywhere anywhere multiport dports ftp-data,ftp,ftps
ACCEPT tcp -- anywhere anywhere tcp dpt:ftp

ufw 和 firewalld

注意, ufw 一般为 ubuntu 系统默认安装的防火墙规则管理软件, firewalld 为 centos 默认按照的防火墙规则管理软件, 这两者是不能同时共存的, 否则会产生冲突, 具体问题可以参考下面的问题描述.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1. 操作前的系统环境
系统: ubuntu
firewalld: 已启动并设置了某些端口
ufw: 未开启

2. 此时按照vsftp安装文档进行了设置, 在配置结束之后, 此时发现如下现象:

a. 本地可以通过公网IP连接ftp服务
b. 其他机器通过公网IP无法连接该ftp服务, 报错: connected refused

3. 此时设置ufw, 配置20,21,990端口无法仍然无法使用ftp服务, 最后的解决办法:

a. 强制关闭firewall-cmd
b. 重启ufw
最后可以成功进行ftp连接

相反的冲突逻辑也是可能存在的, 对于此类问题有如下几个基本的排查步骤:

    1. 查看服务是否开启: netstat -anp|grep port
    1. 查看 firewall 状态, 若开启, 强制关闭(如果你想使用 ufw, 相反则保留 firewalld): firewall-cmd --state
    1. 查看 ufw 状态: ufw status

netfilter

netfilter 是 unix 内核的包过滤框架(packet filtering framework), 其中 hook 点来注册相应回调处理函数, 其包含 5 个 hook 点, 包经过协议栈时会触发内核模块注册在这里的处理函数, 触发哪个 hook 取决于包的方向, 包的目的地址以及包在上一个 hook 点是被丢弃还是拒绝.

下面几个 hook 是内核协议栈中已经定义好的:

  • NF_IP_PRE_ROUTING: 接收到的包进入协议栈后立即触发此 hook,在进行任何路由判断 (将包发往哪里)之前
  • NF_IP_LOCAL_IN: 接收到的包经过路由判断,如果目的是本机,将触发此 hook
  • NF_IP_FORWARD: 接收到的包经过路由判断,如果目的是其他机器,将触发此 hook
  • NF_IP_LOCAL_OUT: 本机产生的准备发送的包,在进入协议栈后立即触发此 hook
  • NF_IP_POST_ROUTING: 本机产生的准备发送的包或者转发的包,在经过路由判断之后, 将触发此 hook

注册处理函数时必须提供优先级,以便 hook 触发时能按照 优先级高低调用处理函数。这使得多个模块(或者同一内核模块的多个实例)可以在同一 hook 点注册,并且有确定的处理顺序。内核模块会依次被调用,每次返回一个结果给 netfilter 框架,提示该对这个包做什么操作。

引用