快捷搜索:   nginx

Linux squid Cache 拦截

Cache拦截包含了某些网络欺骗,它对理解在客户端和Squid之间的会话有用。我使用图9-1和如下的tcpdump示例输出,来解释当数据包通过网 络时,如何被拦截。

1.用户代理(user-agent)想请求某个资源,它对原始服务器发起index.html请求,例如:www.oreilly.com。它需要原始 服务器的IP,所以先发起一个DNS请求:
Packet 1
TIME: 19:54:41.317310
UDP: 206.168.0.3.2459 -> 206.168.0.2.53
DATA: .d...........www.oreilly.com.....
---------------------------------------------------------------------------
Packet 2
TIME: 19:54:41.317707 (0.000397)
UDP: 206.168.0.2.53 -> 206.168.0.3.2459
DATA: .d...........www.oreilly.com.............PR.....%........PR.
....$........PR...ns1.sonic.net.........PR...ns2.Q........PR
...ns...M...............h.............!.z.......b......
2.现在有了IP地址,用户代理初始化到原始服务器80端口的TCP:
Packet 3
TIME: 19:54:41.320652 (0.002945)
TCP: 206.168.0.3.3897 -> 208.201.239.37.80 Syn
DATA:
3.路由器或交换机注意到目的地址是80端口的TCP SYN包。下一步会发生什么依赖于特定的拦截技术。在4层交换和路由策略上,网络设备简单
的将TCP包转发到Squid的数据链路地址。当squid直接挂在网络设备上时,就这样工作。对WCCP来说,路由器封装TCP包为GRE包。因为
GRE包有它自己的IP地址,它可能被通过多个子网进行路由。换句话说,WCCP不要求squid直接挂在路由器上。
4.Squid主机的操作系统接受到拦截包。对4层交换来说,TCP/IP包并没有改变。
假如包使用了GRE封装,主机会剥离外部的IP和GRE头部,并将原始的TCP/IP包放在输入队列里。
注意squid主机接受到的包是针对外部地址的(原始服务器的)。正常情况下,这个包不匹配任何本地地址,它会被丢弃。为了让主机接受外部数据包,你必须 在大多数操作系统上激活IP转发。
5.客户端的TCP/IP包被包过滤代码处理。数据包必须匹配某个规则,该规则指示内核转交这个包给squid。如果没有这样的规则,内核简单的将包按照 它自己的方式转发给原始服务器,这不是你想要的。
注意SYN包的目的端口是80,但squid可能侦听在不同的端口,例如3128。包过滤规则允许你改变端口号。你不必让squid侦听在80端口。通过 tcpdump,你能见到这步,因为转发的包不会再次通过网络接口代码。
即使squid侦听在80端口,包过滤器的重定向规则仍是必要的。可以让squid不在这些端口上接受拦截包。重定向规则有点神奇,它转交外部数据包给 squid。
6.Squid接受到新连接的通知,它接受这个连接。内核发送SYN/ACK包返回给客户端:
Packet 4
TIME: 19:54:41.320735 (0.000083)
TCP: 208.201.239.37.80 -> 206.168.0.3.3897 SynAck
DATA:
就象你见到的一样,源地址是原始服务器,尽管这个包不会抵达原始服务器。操作系统只是简单的将源地址和目的地址交换一下,并将它放进响应数据包里。
7.用户代理接受到SYN/ACK包,建立起完整的TCP连接。用户代理现在相信它是连接到原始服务器,所以它发送HTTP请求:
Packet 5
TIME: 19:54:41.323080 (0.002345)
TCP: 206.168.0.3.3897 -> 208.201.239.37.80 Ack
DATA:
---------------------------------------------------------------------------
Packet 6
TIME: 19:54:41.323482 (0.000402)
TCP: 206.168.0.3.3897 -> 208.201.239.37.80 AckPsh
DATA: GET / HTTP/1.0
User-Agent: Wget/1.8.2
Host: www.oreilly.com
Accept: */*
Connection: Keep-Alive
8.Squid接受HTTP请求。它使用HTTP Host头部来转换局部URL为完整的URL。在这种情形下,可在access.log文件里见到http://www.oreilly.com。
9.从这点开始,squid正常的处理请求。一般cache命中会立刻返回。cache丢失会转发到原始服务器。
10.最后,是squid从原始服务器接受到的响应:
Packet 8
TIME: 19:54:41.448391 (0.030030)
TCP: 208.201.239.37.80 -> 206.168.0.3.3897 AckPsh
DATA: HTTP/1.0 200 OK
Date: Mon, 29 Sep 2003 01:54:41 GMT
Server: Apache/1.3.26 (Unix) PHP/4.2.1 mod_gzip/1.3.19.1a mo
d_perl/1.27
P3P: policyref="http://www.oreillynet.com/w3c/p3p.xml",CP="C
AO DSP COR CURa ADMa DEVa TAIa PSAa PSDa IVAa IVDa CONo OUR
DELa PUBi OTRa IND PHY ONL UNI PUR COM NAV INT DEM CNT STA P
RE"
Last-Modified: Sun, 28 Sep 2003 23:54:44 GMT
ETag: "1b76bf-b910-3ede86c4"
Accept-Ranges: bytes
Content-Length: 47376
Content-Type: text/html
X-Cache: MISS from www.oreilly.com
X-Cache: MISS from 10.0.0.1
Connection: keep-alive
不应该让交换机或路由器来拦截squid到原始服务器的连接。假如这种情况发生,squid结束与自己的会话,并且不能满足任何cache丢失。
防止这类转发死循环的最好方法是,确认用户和squid连接到交换机或路由器的独立接口。无论何时,应该在指定接口上应用拦截规则。最明显的,不该在
squid使用的接口上激活拦截。
9.2为何要(或不要)拦截?
许多单位发现,cache拦截很有用,因为他们不能,或不愿意所有用户的web浏览器。相对于成百上千台工作站来说,在单个交换机或路由器上做一 点网络欺骗更容易。从我们面临的许多选择来看,cache拦截确实有好也有坏。它可能让你的生活更容易,但也许会更难。
Cache拦截的最明显的贡献是,所有HTTP请求通过squid自动离开你的网络。你不必担心配置任何浏览器,用户可能在浏览器上禁止他们的代
理设置。cache拦截让网络管理员完全控制HTTP会话。你可以改变,增加,或删除squid的缓存,而不会显著影响你的用户上网冲浪。
关于HTTP拦截的主要不利点就是该技术违背了TCP/IP的标准。这些协议要求路由器或交换机转发TCP/IP包到目的IP地址里指定的主机。
然而转发包到cache代理破坏了这些规则。代理伪装身份接受转交过来的连接。用户代理被欺骗了,以为它们在与真正的web服务器会话。
这样的混乱导致在老版本的Microsoft IE浏览器中产生严重问题。浏览器的Reload按钮是刷新HTML页面的最容易的方法。当浏览器
被配置成使用cache代理时,reload请求包含了一个Cache-Control:no-cache头部,它强迫产生cache丢失(或cache
确认),并确保响应是最近更新的。假如没有明确配置使用代理,浏览器会忽略该头部。当使用cache拦截时,浏览器认为它在连接到原始服务器,因此没必要
发送该头部。在这种情形下,squid不会告知用户的Reload按钮,也许不会验证cache响应。squid的ie_refresh提供了解决此
bug的局部解决方法(见附录A)。Microsoft已经在其IE 5.5 SP1中解决了这个问题。
因为类似的理由,你不能结合cache拦截使用HTTP代理验证。因为客户端不知道这个代理,它不会发送必要的Proxy-
Authorization头部。另外,407(代理验证请求)响应代码也不恰当,因为响应看起来象来自原始服务器,原始服务器从来不会发送如此响应。
也不能在cache拦截中使用RFC 1413 ident查询(见6.1.2.11章节)。Squid不能对必要的IP地址建立新的
TCP Socket连接。操作系统在转发拦截连接到squid时,它执行欺骗。然后,当squid希望bind新的TCP Socket到外部IP地址
时,它不能执行欺骗。它想bind的地址实际上并非真正本地的,所以bind系统调用失败。
cache拦截也与设计成阻止地址欺骗的IP过滤冲突(见RFC 2267:Network Ingress Filtering:
Defeating Denial of Service Attacks Which Employ IP Source AddressSpoofing)。
考虑如图9-2显示的网络。路由器有2个LAN接口:lan0和lan1。网络管理员在路由器上使用包过滤器,以确保没有内部主机传送假冒源地址的数据
包。路由器只会转发源地址对应相连网络的数据包。包过滤规则也许看起来如下:
# lan0
allow ip from 172.16.1.0/24 to any via lan0
deny ip from any to any via lan0
# lan1
allow ip from 10.0.0.0/16 to any via lan1
deny ip from any to any via lan1

现在看看,当路由器和lan1中的squid主机配置成拦截来自lan0中的HTTP连接后,会发生什么。Squid装扮成原始服务器,这意味着
从squid到用户的响应TCP包欺骗了源地址。lan0过滤规则导致路由器拒绝这些包。为了让cache拦截生效,网络管理员须移除lan0规则。这样
就让网络有漏洞,从而易遭拒绝服务攻击。
我在先前的章节里描述过,客户端在打开连接之前必须先进行DNS查询。在某些防火墙环境中,这样做可能有问题。你想进行HTTP拦截的主机必须能
够查询DNS。如果客户端了解自己正使用代理(因为手工配置或代理自动配置),它通常就不去解析主机名。代替的,它简单的将完整URL转发给squid,
由squid来查询原始服务器的IP地址。
另一个小问题是,squid接受任意目的IP地址的连接。例如,某个web站点当机了,但它仍然有DNS记录存在。squid伪装这个站点接受TCP连 接。客户端会认为该站点仍然在运行,因为连接有效。当squid连接到原始服务器失败时,它强迫返回错误消息。
万一形势不清,HTTP拦截在初次使用时有些棘手或困难。许多不同的组件必须组合工作,并且要配置正确。甚至,从内存中恢复整个配置也很困难。我强烈建议 你在将其应用于生产环境之前,先建立测试环境。一旦你让它正常运行,请记录每一步细节。
9.3 网络设备
现在你了解了cache拦截的相关细节,让我们看看如何实际让它工作。我们先配置网络设备,它们用来拦截HTTP连接。
9.3.1 内置Squid
在该配置中,你无需交换或网络路由设备来拦截HTTP连接。代替的,squid运行的Unix系统,也就是路由器(或网桥),请见图9-2。

该配置本质上跳过了9.1章的头三步。squid主机充当网络路由器,它接受HTTP连接包。假如你采用此方法,请直接跳到9.4章。
9.3.2 四层交换
许多单位使用四层交换机来支持HTTP拦截。这些产品提供更多的功能,例如健壮性检测和负载均衡。我在这里仅仅讲讲拦截。关于健壮性检测和负载均
衡的信息,请见O'Reilly's Server Load Balancing and Load Balancing Servers,
Firewalls, and Caches (John Wiley & Sons). 下面的章节包含了许多产品和技术的示例配置。
9.3.2.1 Alteon/Nortel
下面的配置来自ACEswitch 180和Alteon's WebOS 8.0.21。网络设置请见图9-4。

客户端连接到端口1,通过端口2连接到因特网,squid运行在端口3。下面的行是交换机的/cfg/dump命令的输出。你无须敲入所有这些
行。甚至,在Alteon的新版软件里,某些命令可能改变了。注意Alteon把这个功能叫做Web Cache重定向(WCR)。如下是处理步骤:
1.首先,你必须分配给Alteon交换机一个IP地址。这是必要的,以便交换机能检查squid的存活状态。
/cfg/ip/if 1
ena
addr 172.16.102.1
mask 255.255.255.0
broad 172.16.102.255
2.Alteon的WCR属于服务负载均衡(SLB)配置。所以,必须使用如下命令在交换机上激活SLB功能:
/cfg/slb
on
3. 现在,用squid的IP地址定义real server:
/cfg/slb/real 1
ena
rip 172.16.102.66
4. 必须定义一个组,并分配给real server一个组号:
/cfg/slb/group 1
health tcp
add 1
5. 下一步定义2个过滤规则。第1条规则匹配HTTP连接(目的端口是80的TCP包),并重定向它们到组1里的server。第2条规则匹配所有其他数据 包,并正常转发它们。
/cfg/slb/filt 1
ena
action redir
sip any
smask 0.0.0.0
dip any
dmask 0.0.0.0
proto tcp
sport any
dport http
group 1
rport 0
/cfg/slb/filt 224
ena
action allow
sip any
smask 0.0.0.0
dip any
dmask 0.0.0.0
proto any
6. 最后一步是给SLB配置指定的交换端口。在端口1上,处理客户端连接(这也是客户端连接的端口),并增加2条过滤规则。在端口2上,仅须配置它正常服务 (例如,向上连接到Internet):
cfg/slb/port 1
client ena
filt ena
add 1
add 224
/cfg/slb/port 2
server ena
为了验证HTTP拦截配置正确并工作良好,你可以使用/stats/slb和/info/slb菜单里的命令。/info/slb/dump是快速有效的 查看整个SLB配置的方法:
>> Main# /info/slb/dump
Real server state:
1: 172.16.102.66, 00:c0:4f:23:d7:05, vlan 1, port 3, health 3, up
Virtual server state:
Redirect filter state:
1: dport http, rport 0, group 1, health tcp, backup none
real servers:
1: 172.16.102.66, backup none, up
Port state:
1: 0.0.0.0, client
filt enabled, filters: 1 224
2: 0.0.0.0, server
filt disabled, filters: empty
3: 0.0.0.0
filt disabled, filters: empty
在该输出里,注意到交换机显示Squid在端口3上可到达,并且运行正常。你也能见到过滤规则1应用到端口1。在端口状态节里,端口1定义为客户端连接端 口,端口2简单的标记为服务端口。
/stats/slb/real命令显示real server(squid)的有用统计:
>> Main# /stats/slb/real 1
------------------------------------------------------------------
Real server 1 stats:
Health check failures: 0
Current sessions: 41
Total sessions: 760
Highest sessions: 55
Octets: 0
大部分统计与任务(例如TCP连接)数量相关。假如再次运行该命令,总共的任务计数会增加。
最后,/stats/slb/group命令显示几乎同样的信息:
>> Main# /stats/slb/group 1
------------------------------------------------------------------
Real server group 1 stats:
Current Total Highest
Real IP address Sessions Sessions Sessions Octets
---- --------------- -------- ---------- -------- ---------------
1 172.16.102.66 65 2004 90 0
---- --------------- -------- ---------- -------- ---------------
65 2004 90 0
假如不止1个real server在组里,该输出会更有趣。
9.3.2.2 Foundry
下面的配置示例来自ServerIron XL,运行的软件版本是07.0.07T12。跟前面一样,客户端在端口1,Internet连接在端
口2,squid运行在端口3。然而,这样的配置少了点东西,因为这里可以激活HTTP全局拦截。Foundry的cache拦截的名字叫做
Transparent Cache Switching(TCS)。请参考图9-4。
首先请给交换机分配1个IP地址,以便执行健壮性检测:
ip address 172.16.102.1 255.255.255.0
Foundry允许你在特定端口上激活或禁用TCS。然而简单起见,这里全局激活它:
ip policy 1 cache tcp http global
在该行里,cache是针对TCS功能的关键字。下1行定义web cache,我定义其名字为squid1,并且告诉交换机它的IP地址:
server cache-name squid1 172.16.102.66
最后的步骤是将web cache加进cache组里:
server cache-group 1
cache-name squid1
假如在转发连接时有问题,请参阅show cache-group命令的输出:
ServerIron#show cache-group
Cache-group 1 has 1 members Admin-status = Enabled Active = 0
Hash_info: Dest_mask = 255.255.255.0 Src_mask = 0.0.0.0
Cache Server Name Admin-status Hash-distribution
squid1 6 3
HTTP Traffic From to Web-Caches
Name: squid1 IP: 172.16.102.66 State: 6 Groups = 1
Host->Web-cache Web-cache->Host
State CurConn TotConn Packets Octets Packets Octets
Client active 441 12390 188871 15976623 156962 154750098
Web-Server active 193 11664 150722 151828731 175796 15853612
Total 634 24054 339593 167805354 332758 170603710
某些输出有些模糊,但通过重复该命令,并且观察计数器的增长,你能了解拦截是否在进行。
show server real提供几乎同样的信息:
ServerIron#show server real squid1
Real Servers Info
Name : squid1 Mac-addr: 00c0.4f23.d705
IP:172.16.102.66 Range:1 State:Active Wt:1 Max-conn:1000000
Src-nat (cfg:op):(off:off) Dest-nat (cfg:op):(off:off)
squid1 is a TRANSPARENT CACHE in groups 1
Remote server : No Dynamic : No Server-resets:0
Mem:server: 02009eae Mem:mac: 045a3714
Port State Ms CurConn TotConn Rx-pkts Tx-pkts Rx-octet Tx-octet Reas
---- ----- -- ------- ------- ------- ------- -------- -------- ----
http active 0 855 29557 379793 471713 373508204 39425322 0
default active 0 627 28335 425106 366016 38408994 368496301 0
Server Total 1482 57892 804899 837729 411917198 407921623 0
最后,使用show logging命令来观察交换机是否显示squid正常或异常:
ServerIron#show logging
...
00d00h11m51s:N:L4 server 172.16.102.66 squid1 port 80 is up
00d00h11m49s:N:L4 server 172.16.102.66 squid1 port 80 is down
00d00h10m21s:N:L4 server 172.16.102.66 squid1 port 80 is up
00d00h10m21s:N:L4 server 172.16.102.66 squid1 is up
注意ServerIron认为服务运行在80端口。以后你会见到squid运行在3128端口的示例。包过滤规则实际上将包的目的地址从80改变为 3128。这导致一些与状态检测有关的有趣结果,我在9.3.2.5节里会讲到。

顶(0)
踩(0)

您可能还会对下面的文章感兴趣:

最新评论