IP路由流程很详细的例子

http://blog.youkuaiyun.com/lnboxue/article/details/52220928
TCP/IP协议簇是目前互联网应用最广的协议栈,谈到TCP/IP协议栈就不能不讲一讲IP路由的问题,因为在我们使用的网络通信中几乎每时每刻都在发生着IP路由的事件……。当你在网络世界中还是一位新手的时候,你也许认为设备之间实现IP路由所需的仅仅是一台设备的IP地址而已,如果你真的这样认为那就错了。每台设备在进行IP路由的时候除了必需的IP地址外还需要很多其他信息来完成数据的封装!我将通过以下网络场景提供的案例一步一步地来分析设备在进行IP路由时将会发生哪些通信事件。




      在这个场景中有两个网络,这两个网络通过一台具有两个以太网接口(F0/0,F0/1)的路由器连接在一起。路由器的这两个端口和你自己电脑上的RJ-45型号的网卡端口是一样的,都是内建在路由器中的。现在我们来看一看当位于网络A的主机A想要和位于网络B的主机B进行通信时都发生了什么?

      主机A打开命令提示符(具体方法:开始——运行——cmd),命令提示符(>)后输入ping 1.1.1.5  当“ping”这个指令被计算机执行的时候,TCP/IP协议栈会调用该协议栈互联网层的“ICMP”协议封装“ping 1.1.1.5”这个请求。

ICMP协议封装如下:
ICMP报头 (主机A) Ping 1.1.1.5
      Host A(主机A)若要将这个ICMP协议封装的请求发送给目标主机B(Host B)就必须要使用IP协议来“运输”该请求。这样,IP协议这个时候就充当了一个邮差的角色,将ICMP这个数据包写上发送者(主机A)的IP地址和接收者(主机B)的IP地址,然后就可以根据这个目标地址(主机B的地址)来“投递”这个数据包了。

IP协议封装如下:

IP报头ICMP报头(主机A) Ping 1.1.1.5

      经过IP协议封装的数据包只是完成了TCP/IP协议簇网络层上的封装,接下来要完成的是数据链路层的封装。在进行数据链路层的信息封装之前主机A还需启动IP路由进程来判断目标主机B在本地网络还是在远程网络。若主机B在本地网络,说明主机B和主机A在同一个逻辑子网中,也就是同一个IP网段内。若主机B在远程网络则说明主机B与主机A不在同一个网段内,比如本例中,主机A位于网络A而主机B位于网络B。显而易见,在本例的网络场景中主机A会判断出主机B位于远程网络。那么问题是主机A是如何做出判断的呢?
      首先主机A将自己的IP地址和子网掩码作“与运算”。所谓与运算就是无论是二进制的“0”和“1”相与还是二进制的“0”和“0”相与,得出的结果都为“0”,而只有二进制“1”和“1”相与得出的结果为“1”。比如本例中,主机A的IP地址为192.168.0.5,将这个IP地址转换为二进制就是:11000000 10101000 00000000 00000101
      主机A的子网掩码为255.255.255.0,将该掩码转换为二进制就是:11111111 11111111 11111111 00000000 将主机A二进制形式的IP地址和子网掩码作“与运算”的结果是:  11000000 10101000 00000000 00000000
      为了方便查看将这个“与运算”的结果再转换为点分十进制的数就是:192.168.0.0
      这样主机A就通过“与运算”完成了IP路由判断的第一步。接下来的第二步是将目标主机(主机B)的IP地址与发送方(主机A)的子网掩码作“与运算”,比如本例中,主机B的IP地址为1.1.1.5,将这个IP地址转换为二进制就是:00000001 00000001 00000001 00000101
      主机A的子网掩码为255.255.255.0将该掩码转换为二进制就是:11111111 11111111 11111111 00000000 将以上两组二进制的数进行“与运算”的结果是:00000001 00000001 00000001 00000000 将这个“与运算”的结果转换为点分十进制的数就是:1.1.1.0 这样我们就得到了两组“与运算”的结果,分别是:192.168.0.0和1.1.1.0
      对于主机A来说,经过这样一番“与运算”后,如果两个“与运算”结果相同,则说明目标主机B和自己在同一个网络内,即目标主机B在本地网络。相反地,对于主机A来说,经过这样一番“与运算”后,如果两个“与运算”结果不同,则说明目标主机B和自己不在同一个网络内,即目标主机B在远程网络。在本例中,很显然目标主机B对于发送方(主机A)来说在远程网络——也就是在网络B。
      主机A通过以上与目标主机B略显复杂的“与运算”后,完成了路由判断的第一步——判断出了目标主机B在远程网络。接下来主机A需要“思考”的是如何才能够到达主机B所在的网络?主机A首先会查询自己的路由表,看在自己的路由表中能否找到去往目标网络(网络B)的路由条目。为了方便大家理解,我将主机A的路由表输出显示如下:


C:\>route print
Active Routes:
Network Destination         Netmask             Gateway          Interface         Metric
               0.0.0.0             0.0.0.0            192.168.0.1      192.168.0.5         10
             127.0.0.0          255.0.0.0            127.0.0.1         127.0.0.1           1
           192.168.0.0     255.255.255.0      192.168.0.5      192.168.0.5         10
           192.168.0.5   255.255.255.255       127.0.0.1         127.0.0.1           10
         192.168.0.255   255.255.255.255   192.168.0.5      192.168.0.5         10
             224.0.0.0           240.0.0.0         192.168.0.5      192.168.0.5         10
       255.255.255.255  255.255.255.255   192.168.0.5      192.168.0.5         1

Default Gateway: 192.168.0.1

      从主机A路由表的输出显示中我们没有找到与目标主机B所在的网络相匹配的具体路由,也就是说主机A没有到达1.1.1.0这个网络的路由。但是我们注意到在该路由表的最后一行输出的是:  Default Gateway(默认/缺省网关): 192.168.0.1 路由表最后一行的输出说明主机A在没有找到能够到达目标网络的具体路由的情况下,会将发往目标网络的数据包发送到默认/缺省网关(192.168.0.1),由这个默认/缺省网关再将该数据包转发到目标网络。
      好了,现在主机A知道了默认网关(192.168.0.1)是自己的下一跳地址,主机A开始执行封装。封装信息如下:


目的MAC:
下一跳设备的MAC
源MAC:
主机A的MAC地址
源IP:
192.168.0.5
目的IP:
1.1.1.5
ICMP报头 (主机A)
Ping 1.1.1.5
     
      在以上所封装的寻址信息当中,主机A唯一不知道的就是“下一跳设备的MAC地址”,这里的“下一跳设备MAC地址”是指主机A的默认网关192.168.0.1的F0/0接口的MAC地址。这里容易让人产生一个困惑,主机A的目的IP地址是主机B,那么为什么主机A封装的链路层的目的MAC地址却是路由器F0/0的MAC地址呢?原因是当初人们在设计数据链路层时主要考虑如何解决一条线路上相邻两端设备之间的通信。
      从这个网络场景中我们看到主机A和主机B从各自所处的物理位置上看并不属于相邻的两台设备(中间隔着一台路由器)。既然主机B并不是主机A直接相邻的设备,那么主机A在数据链路层封装的目的MAC地址当然就不可能是主机B了。主机A通过IP路由的流程判断和查询路由表知道要想到达主机B就必须将数据包发给路由器A的F0/0接口(F0/0接口也是主机A到达主机B必经的直接相邻的接口),因此F0/0的MAC地址就成为主机A在数据链路层封装的目的MAC地址。在本例中假如主机A要给Server A发送数据而不是给主机B,那么主机A在数据链路层封装的目的MAC地址就是Server A的MAC地址,因为Server A与主机A是彼此直接相邻的设备。那么对于主机A来说它是否知道路由器F0/0接口的MAC地址呢?主机A是不知道的。所以接下来主机A需要做的是如何才能找到F0/0接口的MAC地址以完成数据链路层的封装成帧。首先主机A查看自己的ARP缓存表,每台主机/电脑都有这个ARP缓存表,该缓存表记录着与自己发生过通信的所有的直接相邻设备或主机的硬件地址(MAC地址),ARP缓存表经过一段时间会自动删除,比如Windows 的动态 ARP 缓存条目不超过 10 分钟就会被删除。如果主机A与路由器之前曾发生过通信,主机A自然能在ARP缓存表中找到路由器F0/0的硬件MAC地址,可是如果这是主机A与路由器的第一次通信,则主机A会向网络A上发送发送ARP广播请求数据包,该ARP请求包包含的关键信息如下:


发送方IP地址(192.168.0.5) 发送方MAC地址(主机A MAC地址)
目的IP地址(192.168.0.1) 目的MAC地址(000000000000)

      以上ARP请求包中封装的三项信息都是已知的,只有“目的MAC地址”这一信息是未知的(全“0”填充)。当该ARP请求包发送到网络A上时,网络A上的设备接收该ARP包并查看该ARP包内的具体封装信息。因为该ARP包中封装的目的IP地址是192.168.0.1,所以只有具有192.168.0.1这个IP的接口或设备才应答该ARP查询请求,应答者会将自己的硬件MAC地址封装到这个ARP应答数据包中。这个ARP应答数据包(本例中由路由器F0/0接口发出ARP应答)封装的关键信息如下:


发送方IP地址(192.168.0.1) 发送方MAC地址(F0/0接口MAC地址)
目的IP地址(192.168.0.5) 目的MAC地址(主机A的MAC地址)
   
      主机A通过ARP协议解析出路由器F0/0接口的MAC地址从而完成了数据链路层的封装。通过主机A这个解析过程大家可以看到主机A在第一次与默认网关通信时的确是费了一番周折,为了找到默认网关F0/0接口的MAC地址也“耽搁”了一些时间,这也是为什么我们在第一次ping网络上某台主机/设备的时候通常会看到第一个数据包会出现“request timed out!”(请求超时!)的情况。最后主机A完成MAC地址解析后将该帧发送到网络A上,该帧的具体封装如下:


目的MAC:
路由器F0/0接口
源MAC:
主机A的MAC地址
源IP:
192.168.0.5
目的IP:
1.1.1.5
ICMP报头 (主机A) Ping 1.1.1.5

      因为该帧的目的MAC地址是F0/0的MAC地址,所以只有路由器的F0/0接口接收并处理该数据帧。路由器将该帧解封装并查看网络层的封装信息,路由器看到该数据包网络层封装的目的地址是1.1.1.5。路由器为了将这个数据包转发到1.1.1.5,使用前面提到的“与运算”的方法进行计算,依据计算结果判断目标地址1.1.1.5对于路由器自己来说在本地网络还是在远程网络。路由器所做“与运算”过程简述如下:

      路由器的F0/0接口上的IP地址192.168.0.1与F0/0接口的子网掩码255.255.255.0作“与运算”得到“结果1”;目标地址1.1.1.5与路由器F0/0接口的子网掩码255.255.255.0作“与运算”得到“结果2”;“结果1”与“结果2”并不相同,证明目标地址1.1.1.5并不处在路由器的F0/0接口所在的网络A。
      路由器的另一个接口F0/1的IP地址1.1.1.1与F0/1接口的子网掩码255.255.255.0作“与运算”得到“结果3”;目标地址1.1.1.5与F0/1接口上
的子网掩码255.255.255.0作“与运算”得到“结果4”;“结果3”与“结果4”相同,证明目标地址1.1.1.5处在路由器的F0/1接口所在的网络B。这也就意味着路由器B只需将发送给1.1.1.5的数据包从F0/1接口发出去就OK了。我们将路由器的这种路由称为直接路由。

      路由器得出上述结论后立刻执行封装,封装的具体信息如下:

目的MAC:
主机B的MAC地址
源MAC:
路由器F0/1接口
源IP地址
192.168.0.5
目的IP地址
1.1.1.5
ICMP报头 (主机A) Ping 1.1.1.5

      在以上路由器封装的具体信息中的目的MAC地址是主机B的MAC地址。如果路由器在ARP缓存表中并未查到主机B的硬件MAC地址,则路由器仍然会像主机A查询路由器F0/0接口硬件MAC地址一样发送ARP请求来查询主机B的MAC地址。关于路由器对主机B 硬件MAC地址的查询过程在这里就不再重复了。
      这样主机B就收到了该数据帧,主机B对该帧进行解封装看到了网络层封装的目的IP地址,知道这个数据包的目的地是自己后,主机B继续对其拆封装并查看ICMP报头内的信息得出结论:这是一个请求自己进行反馈的数据包,需要自己将这条“数据包已到达主机B”的信息回馈给主机A。因此主机B为了将回馈信息顺利送达主机A需要经过如封装:

目的MAC:
路由器F0/1接口
源MAC:
主机B的MAC地址
源IP:
1.1.1.5
目的IP:
192.168.0.5
ICMP报头 对(主机A) Ping 1.1.1.5的应答

      主机B在发送应答数据包时封装的目的MAC地址是路由器F0/1接口的MAC地址,这也是主机B通过路由判断和与运算得出的结论,对于主机B来说路由器F0/1接口是它的下一跳。
      路由器F0/1接口在收到主机B发来的数据包后为了将其转发给主机A再次进行封装,具体的封装信息如下:

目的MAC:
主机A的MAC地址
源MAC:
路由器F0/0接口
源IP:
1.1.1.5
目的IP:
192.168.0.5
ICMP报头 对(主机A) Ping 1.1.1.5的应答

      从主机A到路由器再到主机B执行的封装过程中我们可以看出网络层封装的信息是始终不变的:源IP是192.168.0.5 目的IP是1.1.1.5。始终变化的是一跳一跳的硬件MAC地址。从主机B到路由器再到主机A执行的封装过程中我们同样可以看出网络层封装的信息也是始终不变的:源IP是1.1.1.5目的IP是192.168.0.5。始终变化的还是一跳一跳的硬件MAC地址。
      以上我们在IP路由封装的过程中得到的这一结论并不适用于另外一个网络技术——NAT(网络地址转换)。关于NAT我们将在其他的文章中继续讨论。

<think>好的,用户之前已经问过中继穿透工具的原理和示例,现在他具体问到了Tailscale的IP变化过程。我需要详细解释Tailscale的IP分配机制,尤其是在不同网络环境下的IP变化情况。用户可能想知道为什么Tailscale分配的IP是固定的,或者在不同网络下如何保持通信。 首先,我应该回忆一下Tailscale的基本原理。Tailscale使用WireGuard协议,并通过协调服务器管理节点间的连接。用户可能关心的是,当设备切换网络时(比如从家里Wi-Fi到移动数据),Tailscale的虚拟IP是否会变化,以及背后的机制是什么。 然后,我需要分步骤说明Tailscale的IP分配过程。可能包括注册时的初始分配,密钥绑定,协调服务器的作用。同时,要强调虚拟IP的稳定性,即使设备的公网IP变化,虚拟IP保持不变,这是Tailscale的一个优势。 接下来,用户可能需要具体的例子。比如设备A和B在不同网络下的通信过程,如何通过DERP中继或者直连。这里需要举例说明不同的网络场景,比如NAT类型不同导致无法直连时,如何通过中继传输,但虚拟IP不变。 另外,用户可能对虚拟IP的持久性有疑问。是否需要手动更新,或者更换网络后需要重新认证。应该解释Tailscale的后台服务如何自动维护连接,用户无需干预。 还要考虑用户可能遇到的实际问题,比如IP冲突或者多设备管理。Tailscale的虚拟IP是100.x.x.x的范围内,由协调服务器统一分配,避免冲突。这部分可能需要简单说明。 最后,总结Tailscale的IP管理策略,强调其稳定性和自动化的优点,适合普通用户和开发者使用。同时,提醒用户注意安全措施,比如密钥管理和访问控制,确保合法使用。 需要确保语言通俗易懂,结构清晰,分步骤说明。避免使用过于专业的术语,但必要时解释关键概念,比如DERP、NAT穿透等。结合之前的回答内容,保持一致性,补充用户当前关心的具体细节。</think>### Tailscale IP 地址分配与变化机制详解 --- #### 一、核心特性 **虚拟IP稳定性**: Tailscale 分配的 `100.x.x.x` 地址是**永久性虚拟IP**,具备以下特点: - **网络无关性**:无论设备切换 Wi-Fi/4G/5G 网络,虚拟IP不变 - **跨平台绑定**:同一设备(如手机、PC)在不同系统中共享同一虚拟IP - **密钥锚定**:IP 与设备公钥永久绑定(除非主动重置身份) --- #### 二、IP 分配全流程(以两台设备为例) **步骤1:设备注册** - 设备A首次安装 Tailscale 并登录账号 - 协调服务器为其生成: - **虚拟IP**:如 `100.101.102.103` - **公钥**:基于 WireGuard 的 `wgkey` 算法生成 - 信息存储至 Tailscale 控制平面(Control Plane) **步骤2:设备B加入网络** - 设备B通过相同账号认证 - 分配新虚拟IP:`100.201.53.104` - 控制平面同步双方公钥至对方设备 **步骤3:通信建立** ```bash # 设备A执行(连接设备B的虚拟IP) ping 100.201.53.104 ``` - 实际通信可能通过: - **直连通道**:双方NAT类型允许P2P时(UDP打洞成功) - **DERP中继**:复杂网络下经中继节点(如 `derp-nyc`) --- #### 三、网络切换时的IP行为演示 **场景:笔记本电脑从公司切换到家庭网络** 1. **公司网络** - 公网IP:`203.0.113.5`(NAT后) - Tailscale IP:`100.88.77.66`(稳定不变) 2. **断开Wi-Fi,切换至手机热点** - 公网IP变为:`192.0.2.15`(运营商级NAT) - Tailscale 后台服务自动重连: - 向协调服务器更新新出口IP - 重新尝试与对端设备建立直连或中继通道 - **虚拟IP保持**:`100.88.77.66` 不变 3. **对端设备访问验证** ```bash # 其他设备仍通过原虚拟IP访问 ssh user@100.88.77.66 # 自动路由到新网络出口 ``` --- #### 四、虚拟IP变化的特殊情况 | 触发条件 | 结果 | 恢复方式 | |---------------------------|-----------------------------|------------------------------| | 手动重置节点身份 | 生成新虚拟IP(如`100.90.80.70`) | 需重新授权设备 | | 账号被管理员移除 | 原虚拟IP失效 | 重新加入网络分配新IP | | 跨账号迁移设备(企业版) | 虚拟IP随新账号策略变更 | 依赖管理员配置 | --- #### 五、底层技术支撑 1. **MAGIC DNS** - 自动生成 `<设备名>.<网络名>.ts.net` 域名(如 `pc1.my-network.ts.net`) - DNS记录始终指向虚拟IP,规避公网IP变化影响 2. **连接保持(Keep-Alive)** - 每20秒发送加密心跳包维持NAT映射表 - 网络切换时快速重建最优路径 3. **DERP优先级动态调整** ```bash # 查看当前连接类型(直连/中继) tailscale status --json | jq '.Peer[] | {addr, relay, curAddr}' ``` 输出示例: ```json { "addr": "100.201.53.104:41641", "relay": "derp-sin", // 当前使用新加坡中继 "curAddr": "203.0.113.5:41641" // 对端公网地址 } ``` --- #### 六、开发者调试技巧 1. **强制刷新NAT映射** ```bash sudo tailscale down && sudo tailscale up # 重启服务触发新穿透尝试 ``` 2. **查看详细穿透日志** ```bash tailscale netcheck --verbose # 显示NAT类型、首选DERP节点 ``` 典型输出: ``` IPv4: yes, UDP: true, mapping: symmetric Preferred DERP: Tokyo Latency to regions: - hkg: 45ms (Hong Kong) - nrt: 28ms (Tokyo) ``` 3. **指定中继节点**(企业版功能) ```bash sudo tailscale up --advertise-exit-node --exit-node=derp-fra ``` --- ### 总结 **Tailscale 虚拟IP的核心优势**: - **身份标识永续性**:IP作为设备唯一ID,跨网络、跨平台不变 - **连接智能优化**:自动选择直连/中继,用户无感知切换 - **零配置维护**:IP分配、路由更新全自动化 **适用场景**: - 远程办公:通过固定虚拟IP访问公司内网设备 - 跨国组网:利用最优中继节点降低延迟 - IoT设备管理:无需公网IP实现全球可达
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值