引言
为了防范真实的IP地址暴露带来的危险,我们通常有以下做法:
- WAF
- 本机防火墙
- CDN
万一IP真的暴露了呢?
使用 Firewalld 保护 Docker 端口
在docker容器中,我们采用反向代理,达到在浏览器中输入网址可以正常访问,输入IP地址(或IP+端口号)无法访问的目的。
1. 准备
清除所有 iptables 配置并重启 Docker。否则在启动 Nginx Docker 时可能会看到 failed: iptables: No chain/target/match by that name 错误
iptables -t filter -F
iptables -t filter -X
iptables -t nat -F
iptables -t nat -X
systemctl restart docker
设置 SELINUX 权限
setenforce Permissive
永久设置 SELINUX 权限
修改 /etc/selinux/config 文件,设置 SELINUX=permissive
,使其永久生效(需要重启)
2. 配置 Firewalld
停止 Docker
systemctl stop docker
在 firewalld 中重建 DOCKER-USER iptables chain(请忽略任何警告)
firewall-cmd --permanent --direct --remove-chain ipv4 filter DOCKER-USER
firewall-cmd --permanent --direct --remove-rules ipv4 filter DOCKER-USER
firewall-cmd --permanent --direct --add-chain ipv4 filter DOCKER-USER
添加 iptables 规则到 DOCKER-USER chain
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 1 \
-m conntrack \
--ctstate RELATED,ESTABLISHED -j ACCEPT \
-m comment --comment 'Allow containers to connect to the outside world'
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 1 \
-j RETURN \
-s 172.17.0.0/16 \
-m comment --comment 'allow internal docker communication'
提示: 172.17.0.0/16 是 Docker 的默认子网地址, 也可以改为你实际的 Docker 子网地址
为机器 192.168.51.245(公网IP) 配置允许访问Docker的端口(本例为nginx的80、443),优先级为1(您可以在以后添加更多优先级为 0 的规则。请参见下文)
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 1 \
-o docker0 \
-p tcp -m multiport \
--dports 80,443 -s 192.168.51.245/32 -j ACCEPT \
-m comment \
--comment 'Allow IP 192.168.51.245 to access http and https docker ports'
提示:这里的端口是指的 Docker 的内部端口 80,443,而不是映射的外部端口 8080,8443
阻止所有其他IP。 此规则的优先级最低,您可以稍后在此规则之前添加规则
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 10 \
-j REJECT -m comment --comment 'reject all other traffic to DOCKER-USER'
激活规则
firewall-cmd --reload
启动 Docker
systemctl start docker
配置Nginx
在http{}
中加入
server {
listen 80 default;
listen 443 default_server; #使用https/443时启用
ssl_certificate /www/cert/certificate.pem; #任意证书位置
ssl_certificate_key /www/cert/privatekey.pem; #任意的私钥位置
server_name _;
return 444;
}