Linux ufw(防火墙)使用指南,解决ufw和docker冲突问题,保护你的服务器/VPS

2024-06-17 09:49:50 浏览数 (2)

UFW 是 “简单防火墙” 的缩写,是更复杂的 iptables 实用程序的前端。它旨在使管理防火墙变得像设置端口打开和关闭以及调节允许通过的流量一样简单。

ufw 可以在 Debian 和 Ubuntu 系统中使用,是默认的防火墙配置工具,默认 ufw 是禁用状态,支持 IPv4 和 IPv6。

国内的服务器,一般都会有安全组,如果有安全组,则无须使用 ufw 国外的服务器,一般端口全都是放行的,所以有必要使用 ufw

如果是 CentOS 系统,可以使用 firewalld,强烈建议弃用 CentOS 系统,官方早已经不维护了,会有很多漏洞无法修复。 推荐系统:Debian > Ubuntu >>>>> CentOS

Ubuntu 官网 Firewall 介绍

Ubuntu 官网 UFW 介绍

提示:以下所有命令默认在 root 环境下运行,如果是非 root 环境,则命令需要加前缀: sudo

ufw 使用

更新软件包:
代码语言:javascript复制
apt update

apu upgrade
安装
代码语言:javascript复制
# 安装
apt-get install ufw

# 帮助命令
ufw --help
推荐配置

如果要开启防火墙的话,建议先拒绝所有入站流量,然后逐一打开需要的端口。

代码语言:javascript复制
# 默认阻止入站(不会立即切断你的 SSH 连接,因为防火墙尚未启用)
ufw default deny incoming

# 默认允许出站
ufw default allow outgoing

# 拒绝所有访问(如果配置了入站/出战,这个可以不配置)
ufw default deny

# 根据需求开启端口
ufw allow 22

⚠注意 确保在修改 SSH 端口后,不要关闭当前 SSH 窗口,尝试使用新的端口进行 SSH 登录,以确保没有防火墙或其他网络配置问题,以免被自己锁定出服务器。

启用禁用
代码语言:javascript复制
# 启用
ufw enable

# 查看状态
ufw status verbose

# 禁用
ufw disable

# 防火墙规则存放位置
# /etc/ufw 中的规则文件(后缀名:.rules)

允许拒绝

allow 例子:

代码语言:javascript复制
# 接受 97 端口的 tcp/udp 流量
ufw allow 97

# 接受 97 端口的 tcp/udp 流量,并添加备注
ufw allow 97 comment 'open 97 port'

# 接受 97 端口的 tcp 流量
ufw allow 97/tcp

# 接受 97 端口的 udp 流量
ufw allow 97/udp

# 通过服务名来处理, 会从 /etc/services 中查找端口
ufw allow ssh

# 允许特定IP访问
ufw allow from 1.2.3.4

# 允许特定子网访问
ufw allow from 1.2.3.4/97

# 允许特定IP使用任何协议访问22端口
ufw allow from 1.2.3.4 to any port 22

# 允许特定IP使用任何TCP协议访问22端口
ufw allow from 1.2.3.4 to any port 22 proto tcp

deny 例子:

代码语言:javascript复制
# 拒绝 97 端口的 tcp/udp 流量
ufw deny 97

# 拒绝 97 端口的 tcp 流量
ufw deny 97/tcp

# 拒绝 97 端口的 udp 流量
ufw deny 97/udp

# 通过服务名来处理, 会从 /etc/services 中查找端口
ufw deny ssh

# 拒绝特定IP访问
ufw deny from 1.2.3.4

# 同allow
ufw deny from 1.2.3.4 to any port 22
ufw deny from 1.2.3.4 to any port 22
ufw allow from 1.2.3.4/97 to any port 22 proto tcp
删除
代码语言:javascript复制
# 要删除规则,只需在原始规则前加上删除,删除 80 端口的 tcp 配置
ufw delete deny 80/tcp

# 显示规则的顺序和ID号
ufw status numbered

# 删除编号规则(删除规则,规则将向上移动以填充列表)
ufw delete 1

日志

代码语言:javascript复制
# 启用日志
ufw logging on

# 禁用日志
ufw logging off

Docker不遵守ufw规则

如果你在服务端使用 Docker 映射了某个宿主机端口,然后公网访问这个端口的话,你会发现仍然可以访问,即使 ufw 禁用了这个端口,却不起效果。

因为默认状态下的 Docker 并不遵守 ufw 的防火墙规则

解决ufw和docker的问题

解决方案:https://github.com/chaifeng/ufw-docker

目前新的解决方案只需要修改一个 UFW 配置文件即可,Docker 的所有配置和选项都保持默认。

修改 UFW 的配置文件 /etc/ufw/after.rules ,在最后添加上如下规则:

代码语言:javascript复制
# BEGIN UFW AND DOCKER
*filter
:ufw-user-forward - [0:0]
:ufw-docker-logging-deny - [0:0]
:DOCKER-USER - [0:0]
-A DOCKER-USER -j ufw-user-forward

-A DOCKER-USER -j RETURN -s 10.0.0.0/8
-A DOCKER-USER -j RETURN -s 172.16.0.0/12
-A DOCKER-USER -j RETURN -s 192.168.0.0/16

-A DOCKER-USER -p udp -m udp --sport 53 --dport 1024:65535 -j RETURN

-A DOCKER-USER -j ufw-docker-logging-deny -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 192.168.0.0/16
-A DOCKER-USER -j ufw-docker-logging-deny -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 10.0.0.0/8
-A DOCKER-USER -j ufw-docker-logging-deny -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 172.16.0.0/12
-A DOCKER-USER -j ufw-docker-logging-deny -p udp -m udp --dport 0:32767 -d 192.168.0.0/16
-A DOCKER-USER -j ufw-docker-logging-deny -p udp -m udp --dport 0:32767 -d 10.0.0.0/8
-A DOCKER-USER -j ufw-docker-logging-deny -p udp -m udp --dport 0:32767 -d 172.16.0.0/12

-A DOCKER-USER -j RETURN

-A ufw-docker-logging-deny -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW DOCKER BLOCK] "
-A ufw-docker-logging-deny -j DROP

COMMIT
# END UFW AND DOCKER

或者使用 ufw-docker 工具下载脚本,修改 after.rules 文件配置:

代码语言:javascript复制
# 下载脚本
wget -O /usr/local/bin/ufw-docker https://github.com/chaifeng/ufw-docker/raw/master/ufw-docker

# 赋予权限
chmod  x /usr/local/bin/ufw-docker

# 修改配置文件
ufw-docker install

ufw-docker install 命令做了以下事情:

备份文件 /etc/ufw/after.rules 把 UFW 和 Docker 的相关规则添加到文件 after.rules 的末尾 然后重启 UFW,systemctl restart ufw。现在外部就已经无法访问 Docker 发布出来的任何端口了,但是容器内部以及私有网络地址上可以正常互相访问,而且容器也可以正常访问外部的网络。可能由于某些未知原因,重启 UFW 之后规则也无法生效,请重启服务器。

如果希望允许外部网络访问 Docker 容器提供的服务,比如有一个容器的服务端口是 80。那就可以用以下命令来允许外部网络访问这个服务:

代码语言:javascript复制
ufw route allow proto tcp from any to any port 80

这个命令会允许外部网络访问所有用 Docker 发布出来的并且内部服务端口为 80 的所有服务。

请注意,这个端口 80 是容器的端口,而非使用 -p 0.0.0.0:8080:80 选项发布在服务器上的 8080 端口。

如果有多个容器的服务端口为 80 ,但只希望外部网络访问某个特定的容器。比如该容器的私有地址为 172.17.0.2 ,就用类似下面的命令:

代码语言:javascript复制
ufw route allow proto tcp from any to 172.17.0.2 port 80

如果一个容器的服务是 UDP 协议,假如是 DNS 服务,可以用下面的命令来允许外部网络访问所有发布出来的 DNS 服务:

代码语言:javascript复制
ufw route allow proto udp from any to any port 53

同样的,如果只针对一个特定的容器,比如 IP 地址为 172.17.0.2

代码语言:javascript复制
ufw route allow proto udp from any to 172.17.0.2 port 53

ufw-docker 也是支持 Docker Swarm的, 详细教程及配置参考文章:https://github.com/chaifeng/ufw-docker

本文共 1158 个字数,平均阅读时长 ≈ 3分钟

0 人点赞