(我最初创建了这个问题在 StackOverflow 上但它被关闭了,说它属于 ServerFault)
我想在我的 Raspberry PI(机器 A)上使用 Docker 容器作为特定网站的 VPN 代理,并从同一本地网络上的另一台机器(机器 B)访问该容器。为此,我使用了一个设置了 openvpn 并在其上安装 Nginx 的容器。
我使用 docker-compose 来设置容器:
version: '2'
services:
transmission:
build:
context: .
cap_add:
- NET_ADMIN
devices:
- "/dev/net/tun"
restart: always
ports:
- "80:80"
- "443:443"
dns:
- 8.8.8.8
- 8.8.4.4
容器中的 Nginx 配置如下所示:
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name _ cool;
location / {
resolver 8.8.8.8;
proxy_ssl_server_name on;
proxy_http_version 1.1;
proxy_pass https://coolwebsite.org$request_uri;
proxy_pass_request_body on;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
}
}
然后,如果我启动容器并在 PI 主机(机器 A)的 /etc/hosts 中添加以下行:
127.0.0.1 cool
我可以通过执行以下操作来接收目标网站的内容:
curl http://cool
不幸的是,如果我从机器 B 运行相同的 curl 命令,即使在其 hosts 文件中添加了条目后,这也不起作用cool
(尽管 ping 确实有效):
me@home:~$ telnet cool 80
Trying 192.168.1.35...
telnet: Unable to connect to remote host: Connection timed out
me@home:~$ curl http://cool
curl: (28) Failed to connect to cool port 80: Connection timed out
me@home:~$ ping cool
PING cool (192.168.1.35) 56(84) bytes of data.
64 bytes from cool (192.168.1.35): icmp_seq=1 ttl=63 time=7.10 ms
来自机器 A 的更多诊断:
# netstat -tulnp | sort
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN -
tcp6 0 0 :::22 :::* LISTEN -
tcp6 0 0 :::443 :::* LISTEN -
tcp6 0 0 :::8080 :::* LISTEN -
tcp6 0 0 :::80 :::* LISTEN -
上面列出的端口 8080 对应于另一个容器的端口绑定,可以从机器 B 正常访问。
此外,如果我停止容器并运行sudo nc -l -p 80
以启动临时 Web 服务器,则机器 B 可以curl http://cool
成功运行。这就是为什么我认为 Docker 设置有问题,但是什么呢?我看到一些 SO 答案提到使用,network_mode: host
但如果我的容器与其主机共享相同的 IP,那么它就违背了我通过 VPN 的目的。
如果我可以提供更多信息,请告诉我。
答案1
想法 1 您确定没有主机进程已驻留在端口 80 上吗?
思想2 你的 docker-compose 缺少有关网络模式的任何信息-它是连接到默认网桥还是其他东西?
尝试将网络部分添加到组合中以创建新的自定义桥接。请注意,永远不要使用默认桥接,因为它功能受限。因此,对于您来说,情况如下:
version: '3'
services:
transmission:
build:
context: .
cap_add:
- NET_ADMIN
devices:
- "/dev/net/tun"
restart: always
ports:
- "80:80"
- "443:443"
dns:
- 8.8.8.8
- 8.8.4.4
networks:
- Transmission_Network
networks:
- Transmission_Network
想法 3
你的 nginx 看起来有点不对,例如它server_name cool;
不应该是 `server_name _ cool;
这也不应该是你的默认服务器。试试这个
server {
listen 80;
listen [::]:80;
server_name cool;
location / {
resolver 8.8.8.8;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
proxy_set_header X-Forwarded-Host $http_host;
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
proxy_http_version 1.1;
proxy_pass https://coolwebsite.org;
}
}
注意,我包含了常见的所需代理 set_headers,因为如果您有一个标头设置,则位置将不会从 http 部分中的任何设置继承。