菜鸟笔记
提升您的技术认知

HTTP 代理tips

阅读 : 22

在使用代理的时候,有可能会遇到一些比较棘手而且容易被误解的问题,在这里进行一下说明:

  • 代理URI和服务器URI的不同

        这两个只有一点区别:当客户端直接向web服务器发送请求时,只会发送部分URI(没有方案,主机和端口),例如:

        GET /index.html HTTP/1.0

        User-Agent:SuperBrowser v1.3

        当客户端向代理发送请求时候则会包含完整的URI,例如:

        GET http://www.baidu.com/index.html HTTP/1.0

        User-Agent:SuperBrowser v1.3

        为什么这样呢,这就要涉及到发送的规则了。当客户端要向服务器发送报文时,先要在客户端与服务器之间建立连接,建立连接之后就不需要在显示的发送服务器主机地址等的信息了。当客户端经过代理发送请求报文的时候,代理先接收到请求报文,再将请求报文转发给服务器。在这个过程中,代理寻找目标服务器就需要服务器主机,端口,方案等信息了,如果说没有这些信息那么代理就不知道应该把这个报文转发给哪个服务器了。所以当请求是发送给代理的时候就需要完整的URI了。

  • 虚拟主机的问题

        虚拟主机遇到的问题与上面相似,大家知道虚拟主机是一台服务器上存在多个站点,如果客户端要想虚拟服务器发送请求的话,由于很多站点处在同一个真实服务器上,那么要区分客户端真正要访问的站点就需要主机,方案,端口等信息,这与上面的类似。但是虚拟主机的解决方案略有不同,对于代理服务器使用的是完整URL,而对于虚拟主机使用的是HOST首部。

  • 拦截代理的纠结

        拦截代理有一个特点,那就是对客户端来说是透明的,客户端根本不知道拦截代理的存在,所以会发送不完整的URI。这个时候如果代理服务器或者反向代理接收到这种请求的话,就不知道之后向哪个服务器发送了。

  • 代理既可以处理代理请求,也可以处理服务器请求

        代理可能被用来作为显示代理,也可能作为拦截代理存在。所以代理需要同时具有处理完全URI和HOST首部的能力。如果使用的是完整的URI,代理就直接使用这个完整URI。如果提供的是部分的URI,而且有HOST首部,那么就用HOST来确定服务器的名字和端口号。如果没有完整URI和HOST的话就需要使用其他方法进行确定原始服务器:

  1. 如果代理是原始服务器的替代物,那么就可以用真实的服务器地址和端口来配置代理。
  2. 如果流量被拦截了,拦截者也可以提供原始的IP地址和端口,那么代理就可以使用这个IP和端口了。
  3. 如果以上方法都不可以的话,代理就没有足够的信息确定服务器了,就会返回一条错误报文。
  • 转发过程中对URI的修改

        报文会经过代理就意味着代理可以对报文进行修改。在正常情况下,代理对报文的修改要十分谨慎,即使是一些善意的修改,例如将80端口改为默认的表现形式,这很可能会引发一些意想不到的问题。

  • 自动补完

        在我们使用浏览器的时候,如果输入的是地址的一部分,浏览器就会进行自动补完,例如我在地址栏只输入baidu我也可以访问到百度首页。

        自动补完的解析规则是这样的:

        没有代理时的解析:

  1. 用户在地址栏中输入baidu,浏览器用baidu作为主机名,并以http://为默认方案,80为默认端口,/为默认路径向DNS服务器发送解析请求。
  2. DNS服务器返回结果,表示使用这个主机名进行查找失败了,浏览器则使用www.baidu.com作为主机名,补完方案与端口,再一次向DNS服务器进行解析请求
  3. DNS找到主机,返回正确的IP地址,客户端使用这个IP进行连接。

     可以看出解析是由一定的优先顺序规则组成的,所以补完有时并不是正确的。

        有显示代理时的解析:

        有显示代理的时候,浏览器会直接把URI发送给代理,浏览器自己就不会进行补完工作了。如果用户输入的是baidu,那么浏览器就直接会把http://baidu/发给代理。由于这样的原因,有些代理也会具有自动补完的功能。

        有拦截代理时的解析:

        拦截代理对客户端来说是透明的 ,所以浏览器会对输入的的URI进行类似没有代理时候的自动补完,但是在进行服务器连接的时候会有一个很重要的区别,下面来看下事务处理的过程:

  1. 用户在浏览器中输入baidu。
  2. 浏览器向DNS发送解析请求,解析baidu,但解析失败。
  3. 浏览器对baidu进行自动补完,再一次向DNS发送解析请求。
  4. 这一次DNS找到了主机名,向浏览器返回IP地址表。
  5. 客户端收到IP地址表,有些IP可能已经停止使用了,所以浏览器会尝试每一个IP地址,知道连接成功为止,但是对于拦截代理来说,浏览器发送的第一次请求就会被它拦截住,不会立刻发送到服务器上去,而这时拦截代理在客户端眼中就变成了服务器,认为自己已经找到了服务器,就不会继续尝试剩下的IP了。
  6. 拦截代理尝试连接该IP的服务器,可能会发现这个IP根本是没有用的,而客户端此时已经认为连接成功了,不继续尝试剩下的IP。为了解决这种状况,代理需要一些容错机制,例如使用HOST重新使用DNS进行URI解析,或者使用这个IP进行反向DNS来获取剩下的其他IP来寻找服务器。