我有一台运行多个 Docker 容器的服务器,其配置如下:
- 其中一个容器是绑定到其他容器的公开端口的反向代理。这是唯一一个在 http 端口 80 上接受来自外界连接的容器
- 所有其他容器都是运行 tty shell 的开发环境。这些容器在主机上有公开端口,但由于主机上的 EC2 安全组配置,这些端口不会向外界公开。因此,与它们通信的唯一方法是通过反向代理。反向代理通过它们的公开端口与它们通信。
注:我不能在这里使用容器链接,因为我不想在每个新的开发容器上重新启动反向代理容器。
| DEV Env Docker
| /
OUTSIDE WORLD <-----|------> REVERSE PROXY DOCKER - DEV Env Docker
| \
| DEV Env Docker
这个想法是,用户可以通过反向代理访问开发容器并在该容器内运行命令。
我想通过将用户可以连接的域列入白名单来阻止用户运行连接到外界的命令。
我已经安装了 squid3 并通过在配置文件中添加以下行来设置白名单:
acl whitelist dstdomain "/etc/squid3/whitelist.txt"
http_access allow whitelist
我还设法使用以下 iptables 命令将流量从 docker 容器重定向到 squid iptables -t nat -A PREROUTING -i docker0 -p tcp -d 0/0 -j REDIRECT --to-port 3128
我遇到的问题是,我只希望来自我的 Dev Env 容器的传出流量通过 squid,但由于“我相信”,我需要使用 PREROUTING,所有流量都会通过 squid,即使是传入并发往我的反向代理的流量也是如此。
当我尝试通过 Web 访问我的反向代理时,squid 出现以下错误
ERROR
The requested URL could not be retrieved
The following error was encountered while trying to retrieve the URL: /
Invalid URL
Some aspect of the requested URL is incorrect.
Some possible problems are:
Missing or incorrect access protocol (should be http:// or similar)
Missing hostname
Illegal double-escape in the URL-Path
Illegal character in hostname; underscores are not allowed.
Your cache administrator is webmaster.
Generated Fri, 06 Nov 2015 18:56:54 GMT by ip-10-0-1-201 (squid/3.3.8)
问题:如何让 squid 忽略与反向代理容器相关的所有传入和传出流量?
我的 iptables 是这样的
# Generated by iptables-save v1.4.21 on Fri Nov 6 18:54:09 2015
*nat
:PREROUTING ACCEPT [30:1796]
:INPUT ACCEPT [28:1680]
:OUTPUT ACCEPT [37:2388]
:POSTROUTING ACCEPT [46:2964]
:DOCKER - [0:0]
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A PREROUTING -i docker0 -p tcp -d 0/0 -j REDIRECT --to-port 3128
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
-A POSTROUTING -s 172.17.0.3/32 -d 172.17.0.3/32 -p tcp -m tcp --dport 8000 - j MASQUERADE
-A POSTROUTING -s 172.17.0.3/32 -d 172.17.0.3/32 -p tcp -m tcp --dport 80 -j MASQUERADE
-A POSTROUTING -s 172.17.0.2/32 -d 172.17.0.2/32 -p tcp -m tcp --dport 80 -j MASQUERADE
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 9000 -j DNAT --to-destination 172.17.0.3:8000
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 8192 -j DNAT --to-destination 172.17.0.3:80
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 80 -j DNAT --to-destination 172.17.0.2:80
COMMIT
# Completed on Fri Nov 6 18:54:09 2015
# Generated by iptables-save v1.4.21 on Fri Nov 6 18:54:09 2015
*filter
:INPUT ACCEPT [1891:3910112]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [1500:1500230]
:DOCKER - [0:0]
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A DOCKER -d 172.17.0.3/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 8000 -j ACCEPT
-A DOCKER -d 172.17.0.3/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 80 -j ACCEPT
-A DOCKER -d 172.17.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 80 -j ACCEPT
COMMIT
# Completed on Fri Nov 6 18:54:09 2015
---- 编辑 ----- 如评论中所示,对 http_port 进行更改后,我的 Squid Conf 已完整。
acl SSL_ports port 443
acl Safe_ports port 80 # http
acl Safe_ports port 21 # ftp
acl Safe_ports port 443 # https
acl Safe_ports port 70 # gopher
acl Safe_ports port 210 # wais
acl Safe_ports port 1025-65535 # unregistered ports
acl Safe_ports port 280 # http-mgmt
acl Safe_ports port 488 # gss-http
acl Safe_ports port 591 # filemaker
acl Safe_ports port 777 # multiling http
acl CONNECT method CONNECT
http_access deny !Safe_ports
http_access allow localhost manager
http_access deny manager
acl allowed_ips src 172.17.0.0-172.17.0.254
http_access allow allowed_ips
http_access allow localhost
http_access deny all
http_port 3128 accel vhost allow-direct
coredump_dir /var/spool/squid3
refresh_pattern ^ftp: 1440 20% 10080
refresh_pattern ^gopher: 1440 0% 1440
refresh_pattern -i (/cgi-bin/|\?) 0 0% 0
refresh_pattern (Release|Packages(.gz)*)$ 0 20% 2880
refresh_pattern . 0 20% 4320
我感谢您提供的所有帮助。
答案1
诀窍是让 iptables 仅重定向来自 DEV Env 容器的连接。我们可以通过添加一条规则来接受来自反向代理的所有连接来实现这一点。因此,IP 表规则现在将变为:
-A PREROUTING -i docker0 -s 172.17.0.2/32 -j ACCEPT
-A PREROUTING -i docker0 -s 172.17.0.1/32 -j ACCEPT
-A PREROUTING -i docker0 -p tcp -d 0/0 -j REDIRECT --to-port 3128
由于 docker 动态分配 IP。如果重新运行 docker 容器或重新启动服务器,则需要更新使用的 IP。我还添加了 172.17.0.1 的规则,即 docker0 ip。
这些规则意味着除了反向代理容器和docker主机本身之外的所有其他来自docker0接口的流量都会重定向到squid。
在 squid 中,我们可以使用以下行将域名列入白名单
acl allowed_domain dstdomain google.com
http_access allow allowed_domain
完整的 iptables 规则是:
# Generated by iptables-save v1.4.21 on Fri Nov 6 18:54:09 2015
*nat
:PREROUTING ACCEPT [30:1796]
:INPUT ACCEPT [28:1680]
:OUTPUT ACCEPT [37:2388]
:POSTROUTING ACCEPT [46:2964]
:DOCKER - [0:0]
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A PREROUTING -i docker0 -s 172.17.0.2/32 -j ACCEPT
-A PREROUTING -i docker0 -s 172.17.0.1/32 -j ACCEPT
-A PREROUTING -i docker0 -p tcp -d 0/0 -j REDIRECT --to-port 3128
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
-A POSTROUTING -s 172.17.0.3/32 -d 172.17.0.3/32 -p tcp -m tcp --dport 8000 -j MASQUERADE
-A POSTROUTING -s 172.17.0.3/32 -d 172.17.0.3/32 -p tcp -m tcp --dport 80 -j MASQUERADE
-A POSTROUTING -s 172.17.0.2/32 -d 172.17.0.2/32 -p tcp -m tcp --dport 80 -j MASQUERADE
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 9000 -j DNAT --to-destination 172.17.0.3:8000
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 8192 -j DNAT --to-destination 172.17.0.3:80
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 80 -j DNAT --to-destination 172.17.0.2:80
COMMIT
# Completed on Fri Nov 6 18:54:09 2015
# Generated by iptables-save v1.4.21 on Fri Nov 6 18:54:09 2015
*filter
:INPUT ACCEPT [1891:3910112]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [1500:1500230]
:DOCKER - [0:0]
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A DOCKER -d 172.17.0.3/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 8000 -j ACCEPT
-A DOCKER -d 172.17.0.3/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 80 -j ACCEPT
-A DOCKER -d 172.17.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 80 -j ACCEPT
COMMIT
# Completed on Fri Nov 6 18:54:09 2015
完整的 Squid 规则如下:
acl SSL_ports port 443
acl Safe_ports port 80 # http
acl Safe_ports port 21 # ftp
acl Safe_ports port 443 # https
acl Safe_ports port 70 # gopher
acl Safe_ports port 210 # wais
acl Safe_ports port 1025-65535 # unregistered ports
acl Safe_ports port 280 # http-mgmt
acl Safe_ports port 488 # gss-http
acl Safe_ports port 591 # filemaker
acl Safe_ports port 777 # multiling http
acl CONNECT method CONNECT
http_access deny !Safe_ports
http_access allow localhost manager
http_access deny manager
acl allowed_domain dstdomain google.com
http_access allow allowed_domain
http_access allow localhost
http_access deny all
http_port 3128 accel vhost allow-direct
coredump_dir /var/spool/squid3
refresh_pattern ^ftp: 1440 20% 10080
refresh_pattern ^gopher: 1440 0% 1440
refresh_pattern -i (/cgi-bin/|\?) 0 0% 0
refresh_pattern (Release|Packages(.gz)*)$ 0 20% 2880
refresh_pattern . 0 20% 4320