1. 背景
- 为了给梯子加速,尝试开启 BBR,所以尝鲜的用上了 Debian 9.
新的 TCP 拥塞控制算法 BBR (Bottleneck Bandwidth and RTT) 可以让服务器的带宽尽量跑慢,并且尽量不要有排队的情况,让网络服务更佳稳定和高效。
Linux Kernel 内核升级到 4.9 及以上版本实现 BBR 加速的,由于 Debian9 默认的内核就是 4.9 的内核而且编译了 TCP BBR 的内容,所以可以直接通过参数开启。
- CentOS 6.x 因为内核的原因,所以装 Docker 比较麻烦;CentOS 7 新的防火墙 FirewallD 虽然已经会初步的使用了;但是还要习惯从 server xxxx start[restart|stop] 转到 systemctl ;还有一个 journalctl -xe 查看错误日志的东西。
- 看到网上好多的 Docker 镜像都是基于 Debian/Ubuntu 的,很少基于 CentOS,所以也为了学习一下 Debian
综合一下,所以 VPS 装了 Debian 9 的系统。
2. 安装梯子
2.1. 脚本安装(支持 Open-VZ)
然后用一键脚本装了 v2ray,放上作者的一键式安装命令
1 | bash <(curl -s -L https://git.io/v2ray.sh) |
确实相当好用,nice。具体链接请点击这里
2.2. Docker 一键安装
我使用的配置方式是 Docker + Caddy + v2ray,走的是 WS + TLS。
传送门:https://github.com/yuanmomo/docker-caddy-v2ray
3. 需求
安装 v2ray 后,需要防火墙禁用一些端口,像用 WS + TLS 时,v2ray 的监听端口只需要 Caddy 能访问就 OK 了,外面是不需要访问的。
如果使用一键脚本安装,又安装了 ss 服务,如果需要手动关闭和打开 ss 的端口,那就要用到防火墙。
在之前的 CentOS 6.x 之前,用 iptables,那是相当的没有问题,但是就是命令太长,所以 Debian(Ubuntu)基于 iptables 封装了一个 ufw,来简化 iptables 的操作。
4. ufw 使用
官方操作文档:https://help.ubuntu.com/lts/serverguide/firewall.html
大概使用如下:
1 | # 启用 ufw,设置默认 incoming 为 deny |
5. 事实?
当我一顿猛如虎的操作了过后,然后看了一下当前 ufw 的状态
1 | # 启用 ufw,设置默认 incoming 为 deny |
默认 deny,只允许访问两个端口: 80 和 22。443 是 ss 端口,不想开放出来,也没有配置在规则里面,简直毫无破绽。
然后美滋滋的在本地执行了一下 nmap 和 telnet( 真实 ip 被我替换掉了):
1 | » telnet 1.1.1.1 443 |
什么鬼???443 怎么可能访问到???我不是没有配置 443 端口吗?默认应该是 deny 的啊???
6. 排查
然后我重新试了好几次,还重装了一次 debian,网上各种谷歌 ufw not blocking port 的关键字,看了官方文档。确认,我的 ufw 操作肯定没有问题。
发工单给 VPS HOST,然后陆陆续续的交流,没有什么进展。
自己也在不停的找问题,最后用 iptables-save 命令检查一下当前iptables 的规则:
1 | root@sz:~# iptables-save |
中间的不重要信息已经省略了。发现有两个地方定义了 80 端口,而且格式还不一样。果断怀疑是一键安装脚本直接使用 iptables 命令操作了防火墙,而不是 ufw,而且,插入的顺序还在 ufw 控制的前面,所以就不受 ufw 控制了。
一看脚本的内容:
真的是就是这个原因。
7. 解决
7.1. 脚本直接用 iptables 修改 防火墙配置
这种情况,注释掉脚本使用 iptables 操作防火墙的部分即可。
7.2. Docker 修 iptables 的配置
这个是我搜出来的,之前也遇到过,只是没有仔细深入去思考,为什么 ufw 不能 deny docker 容器中的端口。
解决办法有三个:
- docker run 不使用 -p 参数. 使用 docker linking or docker networks 替代.
- 监听容器的端口在回环网卡 lo 上,也就是 127.0.0.1:
docker run -p 127.0.0.1:8080:8080 … - 配置 Docker 不要修改防火墙。修改 /etc/docker/daemon.json 文件: { “iptables” : false },然后重启。
建议使用第 1,2 两种方法。第 3 种方法回使容器不能访问外网。