ipv4 https请求未转发到docker容器

时间:2018-09-05 07:45:08

标签: docker nginx

我在Docker和我的ovh服务器(ubuntu xenial)上遇到烦人的问题。 我在服务器上运行了NGINX官方docker镜像(15.x),并将某些端口从服务器转发到docker镜像(以在线托管服务器服务)。

从外部(使用IPV4或IPV6)完成的所有HTTP请求都可以到达NGINX。 但是,使用IPV4完成的HTTPS请求无法到达NGINX(IPV6 HTPPS就像一种魅力)。

我使用tcdump tcpdump -i any port 443 -s0 -n监听了服务器和NGINX docker容器中的端口443

结果:我在服务器和NGINX容器中都看到了IPV6 HTTPS请求。 我仅在服务器上看到IPV4 https请求,而在NGINX容器中却没有看到。 =>看来,这不是“开放端口”问题,因为我设法在服务器上看到IPV4请求(并且我检查了IPTables,将443转发给了docker proxy)。 我认为这是我的服务器和Docker代理之间的端口转发pb,仅用于使用IPV6完成的HTTPS请求。

这是我的容器配置:

nginx:
depends_on:
  - my_php7
image: nginx:latest
volumes:
  - "../:/usr/share/nginx/html:rw"
  - "./nginx/var/log:/var/log/nginx:rw"
  - "./nginx/nginx.template.conf:/etc/nginx/conf.d/nginx.template:rw"
  - "./nginx/sites-available:/etc/nginx/sites-available:rw"
  - "./nginx/sites-enabled:/etc/nginx/sites-enabled:rw"
links:
  - my_php7:webstack_php
ports:
  - "8080:8080"
  - "8090:90"
  - "8091:91"
  - "8083:8083"
  - "80:80"
  - "443:443"
restart: always
command: /bin/bash -c "cp /etc/nginx/conf.d/nginx.template /etc/nginx/conf.d/nginx.conf && nginx -c /etc/nginx/conf.d/nginx.conf"

我还检查了net.ipv6.bindv6only:
#> sysctl net.ipv6.bindv6only net.ipv6.bindv6only = 0

这是我的自然信息:

Proto Recv-Q Send-Q Adresse locale          Adresse distante        Etat       PID/Program name
tcp        0      0 0.0.0.0:8081            0.0.0.0:*               LISTEN      19671/node
tcp        0      0 91.121.101.165:914      0.0.0.0:*               LISTEN      1696/openvpn-openss
tcp        0      0 91.121.101.165:915      0.0.0.0:*               LISTEN      1724/openvpn-openss
tcp        0      0 0.0.0.0:8084            0.0.0.0:*               LISTEN      22633/node
tcp        0      0 91.121.101.165:916      0.0.0.0:*               LISTEN      1751/openvpn-openss
tcp        0      0 91.121.101.165:917      0.0.0.0:*               LISTEN      1779/openvpn-openss
tcp        0      0 127.0.0.1:53            0.0.0.0:*               LISTEN      929/named
tcp        0      0 0.0.0.0:21              0.0.0.0:*               LISTEN      947/vsftpd
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      943/sshd
tcp        0      0 127.0.0.1:953           0.0.0.0:*               LISTEN      929/named
tcp        0      0 127.0.0.1:4040          0.0.0.0:*               LISTEN      4765/ngrok
tcp6       0      0 :::8082                 :::*                    LISTEN      12095/docker-proxy
tcp6       0      0 :::8083                 :::*                    LISTEN      12837/docker-proxy
tcp6       0      0 :::2003                 :::*                    LISTEN      12058/docker-proxy
tcp6       0      0 :::9300                 :::*                    LISTEN      12006/docker-proxy
tcp6       0      0 :::85                   :::*                    LISTEN      12070/docker-proxy
tcp6       0      0 ::1:53                  :::*                    LISTEN      929/named
tcp6       0      0 :::22                   :::*                    LISTEN      943/sshd
tcp6       0      0 :::3000                 :::*                    LISTEN      12544/docker-proxy
tcp6       0      0 ::1:953                 :::*                    LISTEN      929/named
tcp6       0      0 :::8090                 :::*                    LISTEN      12861/docker-proxy
tcp6       0      0 :::443                  :::*                    LISTEN      12885/docker-proxy
tcp6       0      0 :::8091                 :::*                    LISTEN      12849/docker-proxy
tcp6       0      0 :::92                   :::*                    LISTEN      12082/docker-proxy
tcp6       0      0 :::4000                 :::*                    LISTEN      12532/docker-proxy
tcp6       0      0 :::9000                 :::*                    LISTEN      12521/docker-proxy
tcp6       0      0 :::5000                 :::*                    LISTEN      12106/docker-proxy
tcp6       0      0 :::3306                 :::*                    LISTEN      12119/docker-proxy
tcp6       0      0 :::80                   :::*                    LISTEN      12897/docker-proxy
tcp6       0      0 :::8080                 :::*                    LISTEN      12873/docker-proxy
tcp6       0      0 :::9200                 :::*                    LISTEN      12035/docker-proxy
tcp6       0      0 :::4400                 :::*                    LISTEN      28319/node
udp6    3072      0 :::40195                :::*                                1081/collectd
udp6       0      0 :::8124                 :::*                                12046/docker-proxy
udp6       0      0 ::1:53                  :::*                                929/named
udp6       0      0 ff18::efc0:4a42:25826   :::*                                1081/collectd

对于那些想知道为什么对于443仅显示IPV6转发的人:

  

在Linux上,默认情况下,net.ipv6.bindv6only为0,因此ipv4数据包可以   也可以从具有ipv4映射的ipv6地址的ipv6套接字接收。从而   您只需要在tcp6套接字上监听,我们就可以同时支持ipv4   和ipv6。

     

如果您想只在ipv4端口上监听,则必须使用   net.Listen(“ tcp4”,“ 0.0.0.0:3000”),然后将侦听器传递给   http.Serve。

我尝试重建容器,但未成功。 我还尝试在另一个docker =>中打开443端口,该端口无法获取IPV4 HTTPS请求。

要恢复:

  • 所有HTTP请求(IPV4 / IPV6)均可

  • 仅IPV6 HTTPS有效,IPV4似乎不被转发给Docker

  • IPtables,Docker conf和网络统计信息都可以。

有什么想法吗? :)

[编辑]

@leodotcloud

确定在这里(我用xxxx隐藏服务器名称)

虚拟主机配置

server {
    listen 443 ssl http2;

    server_name www.xxx.com;

    error_log /var/log/nginx/error.log;
    access_log /var/log/nginx/access.log;

   ssl_certificate    /etc/letsencrypt/live/xxx.com/fullchain.pem;
   ssl_certificate_key  /etc/letsencrypt/live/xxxx.com/privkey.pem;
   ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384;
   ssl_session_timeout  10m;
   ssl_session_cache shared:SSL:10m;
   ssl_prefer_server_ciphers on;

    charset utf-8;

    location / {
        proxy_pass http://node;
        proxy_set_header X-Real-IP  $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
    }

} 

用于SSL的nginx conf

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    ##
    # SSL Settings
    ##

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

....

}

[编辑2] 我试图将docker-compose配置从“ 443:443”更改为“ 0.0.0.0:443:443”以强制ipv4绑定。

我得到了这个错误:Bind for 0.0.0.0:443 failed: port is already allocated

所以我有些东西在443上使用我的IPV4连接。

当我使用“ 443:443”语法绑定IPV6和IPV4时,docker绑定IPV6但不检查IPV4(也许是系统也关心绑定IPV4)。

现在我必须找到此服务。问题:我使用netstat找不到它。有办法强制关闭套接字吗?

[编辑] 我尝试停止容器并直接在服务器上启动nginx,在443 + SSL IPV4 / IPV6上绑定并提供一个“ hello”文件。 => IPV6有效,IPV4不起作用 =>我将端口从443更改为444 => IPV4和IPV6正常工作 =>我清除IPTABLE并在所有内容上配置ACCEPT => IPV4 443还是同样的问题:(

因为Nginx设法绑定到0.0.0.0:443,所以我想套接字是“空闲的”。因此,某些东西正在阻止或过滤从IPV4 443传入的数据

[edit]最后,这是一个IPTABLE问题。我将答案标记为重新打开IPV4中的端口443的解决方案。我将在NAT表中查找导致此问题的规则,并在需要时打开一个新主题。 感谢每个人为您提供帮助和帮助!

1 个答案:

答案 0 :(得分:1)

好吧,我终于找到了使之工作的方法。 我运行了以下命令: iptables -t nat -F

tadaaa一切正常... 我真的不明白该命令的作用。它刷新了NAT规则,但我看不到IPTABLE的任何区别。

如果有人可以告诉我这种“刷新”是否有风险(我从未在IPTABLE中进行任何更改,只有docker对其进行了更改)。