Python网络编程3--实现IP源站路由

2021-08-09  本文已影响0人  净坛使者_猪悟能

一、IP报文首部格式

IP首部

二、实现IP源站路由

2.1 源站路由

  源站路由可以事先规定IP数据包所经过得路由器,每经过一个路由器就改变数据包的目的地址(下一跳)
  使用IP头部中的option字段记录路由IP。该字段最大40字节,因此最多存放9个IP,记录格式如下:


源站路由

Type:占1字节,code 的值此处设为137。

length:占1字节,记录整个选项的长度。
pointer:指针项,占1个字节,指向下一个被处理的源站地址,最小值为4。

2.2 运行过程

  发送主机从应用程序接收源站路由清单,最后一个表项(它是数据报的最终目的地址),剩余的为所有经过的下一跳,每经过一个设备都会检查是否是最终目标,如不是则从列表中读取下一项作为数据包下一跳的目的地址,同时数据包每从一个路由器发出,就记录其出接口的地址,用其替换掉清单中的上一跳地址,数据包返回时任然按照原来的路径返回。
  如下图,主机S上的发送应用程序发送一份数据报给D,指定源路由为R1,R2和R3。#表示指针字段,其值分别是4、8、12和16(一个值表示一个32位IP)。长度字段恒为1 5(三个IP地址加上三个字节首部)。可以看出,每一跳IP数据报中的目的地址都发生改变。


IP源路由

2.3 Python实现

#!/usr/bin/python3.4
# -*- coding=utf-8 -*-

from kamene.all import *
import struct

def ip_sec(ip):
    '''对IP地址进行Bytes转换'''
    ip_l = ip.split(".")
    a = struct.pack(">B", int(ip_l[0]))
    b = struct.pack(">B", int(ip_l[1]))
    c = struct.pack(">B", int(ip_l[2]))
    d = struct.pack(">B", int(ip_l[3]))
    return a + b + c + d

def try_lsrr(dst,lsrr_hop):
    r2=ip_sec(lsrr_hop[1])
    D=ip_sec(dst)
    ip_options = b'\x83\x0B\x04'+r2+D+b"\x00"
    #\x83表示宽松源站路由,\x0B表示长度,\x04表示指针,紧跟着四个字节的IP地址(真正的目的地址),\x00补齐8字节边作为结束位。
    #长度为:3(前options前3字节)+8(r2+D)字节
    pkt = IP(dst=lsrr_hop[0], options=IPOption(ip_options))/ICMP(type=8,code=0)
    #目的地址为源站路由的地址,正真的目的地址放在IP选项内
    a=sr1(pkt,timeout = 1, verbose=True)
    result = a
if __name__ == '__main__':
    dest=input("目的IP>>>")
    lsr_route=input("经过的下一跳>>>")
    lsr_hop=lsr_route.split(" ")
    try_lsrr(dest, lsr_hop)
上一篇 下一篇

猜你喜欢

热点阅读