环境:A(win2k)机器使用内网地址192.168.0.2,它通过B(linux rh9)机器NAT上网,B的eth0是外网地址,B的eth1是内网地址192.168.0.1,由于某些原因,使得这三条线接在同一个交换机上,C(linux rhel4)是另一台NAT服务器(宿舍区用),eth0外网地址,eth1内网192.168.0.1.示意图如下。
发生如下问题,B.eth1重启后报地址冲突,配置一个随机地址192.168.0.33,ping 192.168.0.1.arp -n有192.168.0.1的记录,在C.eth0上抓包,发现有arp应答C.eth1的地址,郁闷。
|------A
|------eth0 B eth1---
| |
|--------------------
|
|------ eth0 C eth1 -----
查看内核arp_rcv(kernel 2.4.0)的代码,
arp_rcv()
{
if (arp->ar_op == __constant_htons(ARPOP_REQUEST) &&/*处理正常的ARP请求*/
ip_route_input(skb, tip, sip, 0, dev) == 0) {/*且在路由表中找到目标IP得路由信息,并保存在skb->dst中*/
}
C接收到arp请求后会先路由
ip_route_input_slow()
{
if (res.type == RTN_LOCAL) {//到本机
int result;
//验证源地址的有效性
result = fib_validate_source(saddr, daddr, tos, loopback_dev.ifindex,
dev, &spec_dst, &itag);
if (result < 0)//验证失败
goto martian_source;
}
fib_validate_source()
{
no_addr = rpf = 0;//反向路径过滤 reserve path filter
read_lock(&inetdev_lock);
in_dev = __in_dev_get(dev);
if (in_dev) {
no_addr = in_dev->ifa_list == NULL;
rpf = IN_DEV_RPFILTER(in_dev);
}
read_unlock(&inetdev_lock);
}
#define IN_DEV_RPFILTER(in_dev) (ipv4_devconf.rp_filter && (in_dev)->cnf.rp_filter)
因此可以在在B和C上打开rp_filter,echo 1 >/proc/sys/net/ipv4/conf/all/rp_filter
这样可以保证C不再响应B上ping 192.168.0.1.
但是还B.eth1使用192.168.0.1地址,service network restart还是报地址冲突错
arp_rcv()
{
if (sip == 0) {//检查IP地址是否重复
if (arp->ar_op == __constant_htons(ARPOP_REQUEST) &&
inet_addr_type(tip) == RTN_LOCAL)//到本机的地址/*如果DHCP询问的,且目标地址是本机地址,则ARP响应;否则将包丢弃*/
//源mac=dev_addr,目的mac=sha,
//源hw=目的hw=dev_addr
//源ip=目的ip=tip
arp_send(ARPOP_REPLY,ETH_P_ARP,tip,dev,tip,sha,dev->dev_addr,dev->dev_addr);
goto out;
}
}
可见需要丢弃这种检测包,那就使用arptables吧,正好B和C都支持
arptables -A INPUT -i eth0 -d 192.168.0.1 -j DROP
搞定
这个问题的主要症结就是B.eth1和C.eth0在同一个局域网当中,如果能隔离开,就没有这么多麻烦事了.
阅读(1152) | 评论(0) | 转发(0) |