在linux上用TUN/TAP构建6to4隧道

一个在linux上用TUN/TAP建立6to4隧道的小程序

        6to4可以在没有原生IPv6接入时构建IPv6 over IPv4隧道。该协议已经被linux内核所支持,内核提供了虚拟设备sit自动配置IPv6隧道。很多ISP也提供免费的TunnelBroker。但如果内核没有支持sit设备(比如现在大多数OpenVZVPS的内核时都没有支持sit),则在运行

# ip tunnel add 6to4 mode sit

会出现

ioctl: No such device

        搜索了一下,似乎还没有运行于linux的第三方程序能建立6to4隧道,于是只好自己写一个。程序放在了

Please visit http://code.google.com/p/tb-tun/

        RFC3056包含了6to4隧道大多数细节,我只看了数据包封装,十分简单,把IPv6数据包(包括header和payload)直接作为IP数据包的packet body。注意IPv4数据包的协议类型为41(C语言里面定义常数IPPROTO_IPV6)。

        程序首先创建TUN设备,并开启SOCK_RAW监听协议41(由于用了原始套接字,运行时必须要有root权限)。然后创建两个线程s2t和t2s,s2t把sock上监听到源地址正确、协议类型为41的IP包去掉包头写入TUN设备,t2s读取TUN设备上的数据并封入IP数据包作为内容发送给Relay Server。

        t2s比较容易,惟一疑惑是使用sendto()函数时,远端地址结构体remoteaddr.sin_port不知道如何填写,因为封装的不是TCP或者UDP,没有端口号。填写为htons(IPPROTO_IPV6)没有出现问题。

        s2t则出现了一些问题,明明向TUN设备写入了正确的数据包,却无法正确被应用程序识别,tcpdump返回wrong link-layer encapsulationbad-hlen。

        重新查看了内核TUN/TAP设备的文档,原来TUN设备模拟点对点链路,也存在链路数据包头。通常创建TUN/TAP设备时使用了flag IFF_NO_PI缺省了链路层包头,内核自动把协议字填写为IP数据包。与实际的IPv6不符导致错误。
        flag IFF_NO_PI没有设置时,链路附加包头为:

struct tun_pi {
    unsigned short flags;
    unsigned short proto;
};

        flag仅在接收数据包时有效,这里向TUN设备写入,即发送数据包,这一字可以置0,proto应该填写htons(ETH_P_IPV6)。

        向TUN写入时,需要在从sock读取的IPv6数据包前加入4个字节的上述结构体。t2s函数也要进行相应修改,除去上述的4个字节链路包头。

        如何配置6to4 tunnel参阅Google Code上的HOWTO。试验了一下资源占用,内存占用约0.5M,CPU使用为wget的2倍。没有测试过兼容性,代码也显然还有很大改进空间。

10年6月更新

        已添加ISATAP支持:

http://www.lostriver.net/tb-tun-now-supports-isatap/

This entry was posted in 互联网 and tagged , , , . Bookmark the permalink.

8 Responses to 在linux上用TUN/TAP构建6to4隧道

  1. Pingback: 梦.:如此短暂

  2. Jude says:

    构建成功,谢谢!

  3. Phil says:

    linux下建6to4隧道可以用freenet6

    • LostRiver says:

      @Phil, 我的程序主要是为内核没有sit设备OpenVZ平台的VPS准备的,freenet6我曾经关注过,既然你提到我又查了一下freenet6的原代码,它建6to4还是用到了内核的sit设备,很多OpenVZ平台就不行了。不过它还提供了v6udpv4的模式,通过UDP建tunnel看来可行。不知道与HE的线路相比谁更快呢?

  4. @qhgy says:

    感谢。加油。

  5. asfly says:

    Thanks for this!
    Can you write some init script, to start it on boot, for linux retarded people like me lol :)

  6. HelpMe says:

    I use OpenVZ client OS Centos 5.4
    when i ran
    setsid ./tb_userspace tb 1.1.1.1 2.2.2.2 sit > /dev/null
    i got error :
    tun_create: Permission denied

    can you help me ?

    • LostRiver says:

      TB-TUN needs tun/tap device, which must run with root privilege.
      You can try su or sudo command before tb_userspace.

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>