本文简要介绍了网络代理自发现协议(Web Proxy Auto-Discovery Protocol,WPAD)的原理。以及 WPAD 借助 DNS 服务器或 DHCP 服务器的实现原理,并重点讨论了利用 DHCP 服务器来实现 WPAD。

曲 巍, 高级软件工程师, IBM

曲巍任职于 IBM CSTL 部门的高级软件工程师,从事 IBM System x 系统工具的研发工作。



殷 万妮, 实习软件工程师, IBM

殷万妮任职于 IBM CSTL 部门的实习软件工程师,从事 IBM System x 系统工具的研发工作。



2013 年 10 月 08 日

WPAD 通过让浏览器自动发现代理服务器,使代理服务器对用户来说是透明的,进而轻松访问互联网。WPAD 可以借助 DNS 服务器或 DHCP 服务器来查询代理自动配置(PAC)文件的位置。

引言

代理服务器大多被用来连接 INTERNET (国际互联网)和 INTRANET(企业内部网)。在多个局域网中需设置不同的代理服务器参数来使浏览器访问网络。在微软 Internet Explorer ( IE )5.0 以上版本中的功能中已经具备了自动切换代理服务器的功能。网络管理员需要事先部署代理服务器配置文件,然而用户方的设置却很简单。在这一功能中使用了被称为“WPAD”(Web Proxy Auto-Discovery protocol)的协议。

浏览器原本具有读入并解析代理服务器的配置文件,并将其配置信息设置到浏览器中的功能。配置文件是使用 Java Script 描述的,通常具有“.js”,“.jvs”,“.pac”(proxy auto-configuration)等扩展名的文件。

自动代理检测由系统确定,Web 代理服务器代表客户端发送请求。自动代理检测启用时,系统会尝试定位到代理发送请求后返回的代理配置文件位置。若查找到代理配置文件,那么在使用 Web 代理服务器实例得到代理信息、数据请求或响应信息时,在本地计算机上进行下载,编译并运行。

被部署的大多数配置文件的格式是 Proxy auto-config (PAC)。最初,PAC 是由 Netscape 在 1996 年为 Netscape Navigator 2.0 设计的。WPAD 协议草案由 Inktomi、微软、RealNetworks、Sun Microsystems 几个公司共同提出。WPAD 可支持所有主流浏览器,首次存在于 Internet Explorer 5.0 中。

WPAD 对代理服务器的透明处理使得管理员不再需要去每台客户机上设置代理服务器参数了。自动检测受动态主机配置协议 (DHCP) 和域名系统 (DNS) 的支持,浏览器通过 DHCP 和 DNS 的查询来搜索 PAC 文件的位置。


Proxy Auto-Config(PAC)文件

在开始介绍 WPAD 原理之前,有必要首先对代理自动配置(PAC)文件有一个概念上的认识。代理自动配置(PAC)文件定义了浏览器和其他用户代理如何自动选择适当的代理服务器来访问一个 URL。要使用 PAC,我们应当在一个网页服务器上发布一个 PAC 文件,并且通过在浏览器的代理链接设置页面输入这个 PAC 文件的 URL 或者通过使用 WPAD 协议告知用户代理去使用这个文件。

一个 PAC 文件是一个至少定义了一个 JavaScript 函数的文本文件。该函数 FindProxyForURL(url, host)有 2 个参数:

url 是一个对象的 URL;

host 是一个由这个 URL 所衍生的主机名。

按照惯例,这个文件名字一般是 proxy.pac。 WPAD 标准使用 wpad.dat。一个非常简单的 PAC 文件内容如下:

function FindProxyForURL(url, host) {
   if (url== 'http://www.baidu.com/') return 'DIRECT';
   if (host== 'twitter.com') return 'SOCKS 127.0.0.10:7070';
   if (dnsResolve(host) == '10.0.0.100') return 'PROXY 127.0.0.1:8086;DIRECT';
   return 'DIRECT';
}

WPAD 的原理

DHCP 的自动检测

通过 DHCP 服务器,管理员可以集中指定全局 TCP/IP 参数和子网特定的 TCP/IP 参数,并可使用保留地址定义客户端的参数。如果客户端计算机在子网之间发生了移动,则在启动该计算机时,会自动重新配置 TCP/IP。

通过 DHCP 服务器部署 WPAD 的原理如下。首先确保 DHCP 服务器有效,然后为每个包含客户的子网建立了作用域。DHCP 服务器中的 252 选项通常被当作查询或注册用的指针,我们可以通过 252 项发现打印机、时间服务器、WPAD 主机以及其他的网络服务器。在 DHCP 服务器中添加一个用于查找 WPAD 主机的 252 项,252 项是一个字符串值,内容是部署在 WPAD 主机上 PAC 文件的 URL。为适当的作用域配置 252 项,就算只有一个作用域。具体部署 DHCP 服务器的操作,请见参考文献:ISA 防火墙之利用 DHCP 部署 WPAD。

因此 DHCP 客户机便可获得 PAC 文件的 URL,当客户机需要对浏览器或防火墙客户端进行自动配置时,就可以下载该 PAC 文件并得到代理服务器的地址。

图 1.DHCP 的自动检测示意图
图 1.DHCP 的自动检测示意图

  

在上图示意中,用户访问 laptop01.us.division.company.com 时,web 浏览器发送 DHCP INFORM 包于 DHCP 服务器来请求配置文件的位置,DHCP ACK 为 DHCP 服务器返回的数据包,其中 252 选项即为代理自动配置文件的位置。DHCP 报文格式如下图:

图 2.DHCP 报文格式
图 2.DHCP 报文格式

OP:消息操作代码,既可以是引导请求(1=BOOTREQUEST)也可以是引导答复(2=BOOTREPLY);

Htype:硬件地址类别,ethernet 为 1;

Hlen:硬件地址长度,ethernet 为 6;

Hops:若数据包需经过 router 传送,每站加 1,若在同一网内,为 0;

Transaction ID:事务 ID,是个随机数,用于客户和服务器之间匹配请求和相应消息;

Seconds:由用户指定的时间,指开始地址获取和更新进行后的时间;

Flags:从 0-15bits,最左一 bit 为 1 时表示 server 将以广播方式传送封包给 client,其余尚未使用;

Ciaddr:用户 IP 地址;

Yiaddr:服务器分配给客户的 IP 地址;

Siaddr:用于 bootstrap 过程中的 IP 地址;(服务器的 IP 地址)

Giaddr:转发代理(网关)IP 地址;

Chaddr:客户机的硬件地址;

Sname:可选 server 的名称,以 0x00 结尾;

File:启动文件名;

Options:厂商标识,可选的参数字段。此参数是 WPAD 实现过程中的关键参数,即相关了 PAC 文件的 URL。

DNS 的自动检测

DNS 是 TCP/IP 网络上的一组协议和服务,通过 DNS,用户可以使用分层的用户友好名称(主机)代替数字 IP 地址来搜索其他计算机。

用 DNS 来实现 WPAD,原理如下:

WPAD 工作原理是客户机向 DNS 服务器发起 WPAD+X 的查询。DNS 返回提供 WPAD 主机 IP 地址,客户机通过该 IP 的 80 端口去 WPAD 主机下载 WPAD.DAT(浏览器配置用文件)和 WSPAD.DAT(防火墙配置用文件)两个文件以实现自动配置。

客户机向 DNS 发起的 WPAD 查询的后缀是根据 WPAD 主机所处的环境决定的,如果客户机是在一个域环境下时,发起的查询便是一个“WPAD.所在域的域名”的标准域名查询,这种情况下配合 DNS 里添加 WPAD 主机的 A 或别名记录便可轻松在域环境中对 WPAD 主机的定位。

但是如果在工作组环境下时,客户机发起的查询可能是一个标准的域名查询(如果计算机名有加域名后缀)也可能只是个没有后缀的 WPAD 查询,这时就要通过创建 DNS 私有根域查询或是通过创建单标签域的方式进行 WPAD 主机查询。

从以上的原理分析,首先 WPAD 主机要在 80 端口提供 wpad.dat 和 wspad.dat,有了这两个文件,客户机上的浏览器或防火墙客户端才能实现自动配置。其次,DNS 服务器要创建相关记录,当客户机来查询时,将解析结果指向 WPAD 主机。

关于 DNS 的自动检测详细的分析,可以参考文献 工作组环境下 WPAD 部署的另类解决

图 3.DNS 的自动检测示意图
图 3.DNS 的自动检测示意图

WPAD 的实现

通过 DNS 服务器部署 WPAD 在域的环境下比较适宜,但在工作组环境下就需要做一些改变。通过 DHCP 服务器部署 WPAD 还是更加方便,既不限制端口,又不受客户机计算机名影响,无论是工作组还是域都能很好地工作。

以下具体讨论了利用 DHCP 服务器来实现 WPAD 的 C++实例,并已通过 gcc 编译。此实例模拟了浏览器使用 DHCP 服务器实现 WPAD 的过程。同时希望能给有需要的开发人员一些关于如何实现 WPAD 的参考。

由上述通过 DHCP 服务器部署 WPAD 的原理,实现分为两大步骤,即向 DHCP 服务器发送 DHCP INFORM 包和接收 DHCP 服务器返回的 DHCP ACK 包,并解析。首先使用 Socket 实现广播(broadcast)的发送和接收来查找 WPAD 主机。广播是指在一个局域网中向所有的网上节点发送信息,是 UDP 协议的一种。在局域网中,广播 DHCP INFORM 包,当 DHCP 服务器接收到广播信息后,返回 DHCP ACK 包于客户机(本机),报文中的 252 选项即为查找的存储在 WPAD 主机上 PAC 文件的 URL。详细如下:

步骤一.查找 DHCP 服务器

  1. 在 WPAD 实现过程中,DHCP 报文为主要的数据结构,dhcp_send 代表 DHCP INFORM 包,dhcp_recv 代表 DHCP 服务器返回的 DHCP ACK 包。
    清单 1.DHCP 报文结构
    typedef struct dhcp_message_ {
         uint8_t op;           /* message type */
         uint8_t hwtype;       /* hardware address type */
         uint8_t hwlen;        /* hardware address length */
         uint8_t hwopcount;    /* should be zero in client message */
         uint32_t xid;            /* transaction id */
         uint16_t secs;           /* elapsed time in sec. from boot */
         uint16_t flags;
         uint32_t ciaddr;         /* (previously allocated) client IP */
         uint32_t yiaddr;         /* 'your' client IP address */
         uint32_t siaddr;         /* should be zero in client's messages */
         uint32_t giaddr;         /* should be zero in client's messages */
         uint8_t chaddr[DHCP_CHADDR_LEN];  /* client's hardware address */
         uint8_t servername[SERVERNAME_LEN];    /* server host name */
         uint8_t bootfile[BOOTFILE_LEN];    /* boot file name */
         uint32_t cookie;
         uint8_t options[DHCP_OPTION_LEN]; /* message options - cookie */
    }dhcp_message;
  2. 广播的实现首先创建 UDP 的 socket,将发送端口 socket 设置为广播类型,开启发送广播报文:
    清单 2.设置发送端口 socket 的属性为广播
    int  bBroadcast=1;
    setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &bBroadcast, sizeof(bBroadcast));
  3. 接收端口绑定地址和这组广播的端口号(DHCP 统一使用两个 IANA 分配的端口作为 BOOTP服务器端 使用 67/udp, 客户端 使用 68/udp),接受广播信息:
    清单 3.绑定端口号
    struct sockaddr_in addr;
    bzero(&addr,sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(DHCP_CLIENT_PORT);//DHCP_CLIENT_PORT=68
    addr.sin_addr.s_addr = inet_addr("10.0.2.15");//local IP
    bind(sockfd, (struct sockaddr *)&addr, sizeof(addr));
  4. 将本机的 IP 地址和 MAC 地址等数据封装成 DHCP INFORM 报文,定义为 dhcp_send:
    清单 4.封装 DHCP 报文
    void make_message(const std::string& ip_addr, const std::string& mac_addr, dhcp_message **message)
    {
        dhcp_message* dhcp;
        dhcp = (dhcp_message*)xzalloc(sizeof (*dhcp));
        bzero(dhcp, sizeof(dhcp_message));
        dhcp->op = 1;
        dhcp->hwtype = 1;  //ARPHRD_ETHER
        dhcp->hwlen = 6;    //MAC ADDR LENGTH
        dhcp->xid = 1983;  //random
        dhcp->ciaddr = GetCiaddr(ip_addr);
        GetChaddr(mac_addr, dhcp->chaddr);
        dhcp->cookie = htonl(MAGIC_COOKIE);
    uint8_t *p = dhcp->options;
    //option 53
        *p++ = DHO_MESSAGETYPE; 
        *p++ = 1;
        *p++ = DHCP_INFORM;
    //option 55
        *p++ = DHO_PARAMETERREQUESTLIST; 
        *p++ = 1;
        *p++ = DHO_PACFILELOCATION;
        *p++ = DHO_END;
        *message = dhcp;
    }
  5. 广播 DHCP INFORM 报文
    清单 5.发送端口发送 DHCP INFORM 广播报文:
    struct sockaddr_in sin;
    bzero(&sin, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr=inet_addr("255.255.255.255");  //Broadcast Address
    sin.sin_port = htons(DHCP_SERVER_PORT);//DHCP_server_PORT=67
    sendto(send_socket_fd, (uint8_t *)dhcp_send,sizeof(*dhcp_send) 0,\
         (struct sockaddr *)&sin,sizeof(sin));

步骤二.接收 DHCP 服务器返回的 DHCP ACK 包,并解析,报文中的 252 项即为查找的存储在 WPAD 主机上 PAC 文件的 URL:

清单 6.将接收端口设置超时选项并接收消息:
struct timeval tv_out;
tv_out.tv_sec = 6;
tv_out.tv_usec = 0;
setsockopt(recv_socket_fd,SOL_SOCKET,SO_RCVTIMEO,&tv_out, sizeof(tv_out));
recvfrom(recv_socket_fd, (uint8_t *)dhcp_recv, sizeof(*dhcp_recv), 0,\
    (struct sockaddr*)&addr,(socklen_t*)&addr_len);
清单 7.解析 DHCP ACK 包
std::string AutoProxyDiscovery::dhcp_parser(uint8_t* options)
{
     uint8_t* p = options;
     int len;
     std::string url;
     while( (p-options) < DHCP_OPTION_LEN )
     {
          if( 252 == *p )
          {
               ++p;
               len = *p++;
               for( int i=0; i<len; ++i,++p)
               {
                    url.push_back(*p);
               }
               break;
          }
          else if( 255 == *p )
          {
               break;
          }
          else
          {
               ++p;
               len = *p++;
               p+=len;     
          }
     }
     return url;
}

步骤三.找到返回的 URL 下/data/wpad.dat 代理配置文件,在本地计算机上下载,编译并运行。即完成了 DHCP 的自动检测。


总结

之前的浏览器通常使用手动代理配置和代理自动配置等,而 WPAD 协议的出现更高级别地实现了自动化。使用 DHCP 来实现 WPAD 的思想较简单,是较好的解决方案。


下载

描述名字大小
示例代码wpad.zip3KB

参考资料

学习

  • 通过代理自动配置 了解有关 PAC 文件的相关知识。
  • 通过DHCP 了解 DHCP 协议相关的详细内容。
  • 通过 域名系统 了解 DNS 的基本知识。
  • 参考findproxyforurl ,了解代理配置文件的部署。
  • 参考 DHCP Messages ,了解 DHCP 报文格式。
  • 访问博客ISA 防火墙之利用 DHCP 部署 WPAD ,了解关于 DHCP 部署 WPAD 的实例。
  • 工作组环境下 WPAD 部署的另类解决 ,了解关于 DNS 部署 WPAD 的实例。
  • AIX and UNIX 专区 :developerWorks 的“AIX and UNIX 专区”提供了大量与 AIX 系统管理的所有方面相关的信息,您可以利用它们来扩展自己的 UNIX 技能。
  • AIX and UNIX 新手入门 :访问“AIX and UNIX 新手入门”页面可了解更多关于 AIX 和 UNIX 的内容。
  • AIX and UNIX 专题汇总 :AIX and UNIX 专区已经为您推出了很多的技术专题,为您总结了很多热门的知识点。我们在后面还会继续推出很多相关的热门专题给您,为了方便您的访问,我们在这里为您把本专区的所有专题进行汇总,让您更方便的找到您需要的内容。
  • AIX and UNIX 下载中心 :在这里你可以下载到可以运行在 AIX 或者是 UNIX 系统上的 IBM 服务器软件以及工具,让您可以提前免费试用他们的强大功能。
  • IBM Systems Magazine for AIX 中文版 :本杂志的内容更加关注于趋势和企业级架构应用方面的内容,同时对于新兴的技术、产品、应用方式等也有很深入的探讨。IBM Systems Magazine 的内容都是由十分资深的业内人士撰写的,包括 IBM 的合作伙伴、IBM 的主机工程师以及高级管理人员。所以,从这些内容中,您可以了解到更高层次的应用理念,让您在选择和应用 IBM 系统时有一个更好的认识。

讨论

  • 加入 developerWorks 中文社区 。查看开发人员推动的博客、论坛、组和维基,并与其他 developerWorks 用户交流。

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Linux
ArticleID=945171
ArticleTitle=WPAD 的原理及实现
publish-date=10082013