代码之家  ›  专栏  ›  技术社区  ›  Matt Ryan

阻止弹性负载平衡器泄露内部私有IP

  •  3
  • Matt Ryan  · 技术社区  · 9 年前

    我注意到,当发出特定类型的请求时,即使在私有子网中,ELB后面的ec2实例的内部IP也会被泄露。特别是具有空HOST值的一个。

    telnet site_url 80
    GET / HTTP/1.0
    

    返回的标题:

    HTTP/1.1 301 Moved Permanently
    Cache-Control: max-age=1209600
    Content-Type: text/html; charset=iso-8859-1
    Date: Thu, 26 Mar 2015 18:47:22 GMT
    Expires: Thu, 09 Apr 2015 18:47:22 GMT
    Location: https://10.0.7.35/
    Server: Apache
    Content-Length: 226
    Connection: Close
    

    这自然也发生在443上的开放ssl请求中。

    有人知道这个问题的解决方案或解决方案吗?我知道IIS也有同样的症状,但我的问题是AWS ELB特有的。

    编辑:

    Apache重定向以强制HTTPS。

    RewriteCond %{HTTPS} off
    RewriteCond %{SERVER_ADDR} !^127\.0\.0\.1
    RewriteCond %{HTTP:X-Forwarded-Proto} !https
    RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
    
    4 回复  |  直到 9 年前
        1
  •  7
  •   Bruce P    9 年前

    这实际上与ELB无关,与Apache无关,这显然是返回这些信息的原因(因此 server: Apache 输出中的行)。

    显然,在Apache配置中定义了某种重定向,将流量从端口80重定向到端口443。您可能应该更新问题,以包含Apache配置文件的相关部分,包括任何重写规则、ServerName、.htaccess设置等。

    编辑:

    您正在重写规则中使用HTTP_HOST,这对应于请求中提供的主机。在您提供的示例中,您没有提供主机,因此请尝试执行以下操作:

    $ telnet www.example.com 80
    GET / HTTP/1.0
    Host: www.example.com
    

    如果定义了虚拟主机,Apache就知道请求应该路由到哪个虚拟主机,那么请求的Host部分是必需的。

    您可能还希望沿以下行添加另一个重写条件:

    RewriteCond %{HTTP_HOST} !^www.example.com
    RewriteRule ^(.*)$ https://www.example.com$1 [R=301,L]
    

    这将确保如果有人试图访问您的网站,而没有提供包含标头的完整请求,那么它将重定向到正确的域。

        2
  •  5
  •   Mike Fiedler    9 年前

    一位朋友今天发布了这篇文章,尽管已经有了答案,但我想我已经把发现的细节写进去了。

    使用原始帖子中描述的机制,我能够再现所描述的场景,其中 Location 返回的头确实是https://address。

    然而,仔细检查后,提供的地址是 我的任何实例地址-更确切地说,它似乎是来自 ELB实例本身 .

    我通过检查ELB后面的一个实例进一步确认了这一点,并使用类似的命令序列,我能够确认 GET / 命令确实是ELB的。

    # These commands are purely to assist in obscuring my own IPs. :)
    $ export LOCALIP=$(ifconfig  | grep 'inet addr:'| grep -v '127.0.0.1' | cut -d: -f2 | awk '{ print $1}')
    $ export DISCOVEREDIP=<the IP from the GET test>
    
    # I'm also using `sed` here to replace real IPs with strings to demonstrate which node is which
    $ ss -tn | grep $DISCOVEREDIP | sed -e "s/$LOCALIP/localip/" -e "s/$DISCOVEREDIP/discoveredip/" | head -n 3
    ESTAB      0      0            localip:80           discoveredip:3950
    ESTAB      0      0            localip:80           discoveredip:4157
    ESTAB      0      0            localip:80           discoveredip:4148
    

    因此,我可以推断出我的web服务器的本地IP地址正在侦听ELB指向的端口80,而ELB的IP正在使用更高的端口连接到我的web server。

    没有超出ELB内部IP地址的暴露,无需担心。快乐的云!

        3
  •  3
  •   James Mernin    9 年前

    最近一天,我们一直在研究这个问题,并得出结论:

    1. 当ELB看到一个没有主机标头的请求时,它必须(真诚地)决定代表您添加一个,并使用自己的私有IP地址作为其值。
    2. 这为Apache提供了一个(更多)有效的请求,因此它生成的任何重定向都使用未修改的HTTP_HOST值。

    我们确实找到了一个适用于我们的解决方案(不过,我们只需要在“默认”VirtualHost中解决这个问题),您可能会考虑将其添加到VirtualHost中:

    UseCanonicalName On
    

    在我们的评估中,这指示一些Apache行为在ServerName指令的响应中正式替换HTTP_HOST,这解决了我们试图解决的问题。

        4
  •  -1
  •   jozwikjp    9 年前

    要解决Varnish Cache中的这个问题,请将我们的公共VPC子网上的IP主机字段重写为我们的主域名。

        if(req.http.host ~ "10.30.0") {
         set req.http.host = "www.mydomain.com";
        }