I/O 带Tun界面
I/O with a Tun interface
目的是让程序拦截一组 IP 数据包并读取其原始内容,然后在修改后将其重新插入网络。
我的方法是建立一个 Tuntap 接口(具体来说是 Tun),然后让 iptables 和类似的工具将所需的数据包重定向到这个隧道接口。
出于测试目的,我编写了这个简短的 shell 脚本来设置 Tun 界面并添加所需的规则。现在,我打算在从我的本地机器发送的目的地为 123.123.123.123
的任何数据包上对此进行测试。这是启动脚本:
# Set up the tunnel
ip tuntap add dev maintun mode tun
ifconfig maintun inet 10.10.10.1 netmask 255.255.255.0 up
# Mark packets for forwarding to tun
iptables -t mangle -A PREROUTING -d 123.123.123.123 -j MARK --set-mark 2
# Apply ClientRouter table to mark 2 as it's defined in /etc/iproute2/rt_tables
# 201 ClientRouter
ip rule add fwmark 2 table ClientRouter
# Apply gw if to ClienRouter
ip route add default via 10.10.10.1 dev maintun table ClientRouter
我开始编写一个 perl 脚本来从 Tun 设备读取数据,但我同时卡在多个点上:
- 在我看来,这样做的方法是让脚本本身通过调用
/dev/net/tun
的文件句柄上的 ioctl()
创建接口,但我不确定其他争论ioctl()
想要。这引出了接下来的两点:
- 我看到对第二个论点的引用是
TUNSETIFF
。我所知道的是它必须是数字。它要求什么?
- 根据我收集到的信息,第三个论点应该是某种旗帜,但我没有设法找到关于它们的信息。据推测,一个标志将用于选择它应该是 Tun 还是 Tap 隧道。有这方面的信息吗?
由于我坚持使用 ioctl() 标志,我想退后一步问:如何以编程方式从 Tun 设备(最好是预先设置的预配置设备)中读取?
此外,如果有人发现启动脚本有任何问题,请随时大声疾呼。
虽然理想情况下解决方案应该是 perl,但不一定是,这只是我最容易阅读的语言。 Java 也不错。不幸的是,我的 C 素养甚至没有达到应有的水平。
编辑:
如果与 Tun/Tap 不同的方法允许我按照第一段中的描述进行操作,当然欢迎任何建议。
注:
我遇到了问题 this question 虽然类似,但它没有提供 ioctl() 争论的答案。然而,这表明需要 ioctl()
调用。
首先,TUN/TAP 接口被记录在案 in the Linux kernel documentation,如果您还没有看过它,值得一读。当然,示例是用 C 语言编写的,但希望仍然有用。
I see references to the second arguement being TUNSETIFF
. All I know is that it has to be numeric. What is it asking for?
这是一个 C 库常量,您可以使用如下代码确定其值:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/if.h>
#include <linux/if_tun.h>
int main(int argc, char **argv) {
printf("TUNSETIFF: %d\n", TUNSETIFF);
return 0;
}
我的系统 returns:
TUNSETIFF: 1074025674
From what I've gathered, the third arguement is supposed to be flags of some sort, but I have not managed to find info on them. Presumably, one flag would be for selecting if it should be a Tun or Tap tunnel. Any info on this?
第三个参数是指向结构的指针,该结构具有
ifr_name
属性,包含设备名称和一个 ifr_flags
包含标志的属性。内核文档提供了
以下示例代码:
/* Flags: IFF_TUN - TUN device (no Ethernet headers)
* IFF_TAP - TAP device
*
* IFF_NO_PI - Do not provide packet information
*/
ifr.ifr_flags = IFF_TUN;
if( *dev )
strncpy(ifr.ifr_name, dev, IFNAMSIZ);
if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ){
close(fd);
return err;
}
您可以找到不同标志的值(IFF_TUN
、IFF_TAP
)
使用上面我们用来查找值的相同代码
TUNSETIFF
.
如果您正在用 Perl 编写代码,您将需要一种方法来创建
相应的 C 兼容结构。我的 Perl 太生锈了建议
我想到了正确的解决方案。
但是,似乎有许多可用的 Perl 模块
简化整个过程:
目的是让程序拦截一组 IP 数据包并读取其原始内容,然后在修改后将其重新插入网络。
我的方法是建立一个 Tuntap 接口(具体来说是 Tun),然后让 iptables 和类似的工具将所需的数据包重定向到这个隧道接口。
出于测试目的,我编写了这个简短的 shell 脚本来设置 Tun 界面并添加所需的规则。现在,我打算在从我的本地机器发送的目的地为 123.123.123.123
的任何数据包上对此进行测试。这是启动脚本:
# Set up the tunnel
ip tuntap add dev maintun mode tun
ifconfig maintun inet 10.10.10.1 netmask 255.255.255.0 up
# Mark packets for forwarding to tun
iptables -t mangle -A PREROUTING -d 123.123.123.123 -j MARK --set-mark 2
# Apply ClientRouter table to mark 2 as it's defined in /etc/iproute2/rt_tables
# 201 ClientRouter
ip rule add fwmark 2 table ClientRouter
# Apply gw if to ClienRouter
ip route add default via 10.10.10.1 dev maintun table ClientRouter
我开始编写一个 perl 脚本来从 Tun 设备读取数据,但我同时卡在多个点上:
- 在我看来,这样做的方法是让脚本本身通过调用
/dev/net/tun
的文件句柄上的ioctl()
创建接口,但我不确定其他争论ioctl()
想要。这引出了接下来的两点: - 我看到对第二个论点的引用是
TUNSETIFF
。我所知道的是它必须是数字。它要求什么? - 根据我收集到的信息,第三个论点应该是某种旗帜,但我没有设法找到关于它们的信息。据推测,一个标志将用于选择它应该是 Tun 还是 Tap 隧道。有这方面的信息吗?
由于我坚持使用 ioctl() 标志,我想退后一步问:如何以编程方式从 Tun 设备(最好是预先设置的预配置设备)中读取?
此外,如果有人发现启动脚本有任何问题,请随时大声疾呼。
虽然理想情况下解决方案应该是 perl,但不一定是,这只是我最容易阅读的语言。 Java 也不错。不幸的是,我的 C 素养甚至没有达到应有的水平。
编辑:
如果与 Tun/Tap 不同的方法允许我按照第一段中的描述进行操作,当然欢迎任何建议。
注:
我遇到了问题 this question 虽然类似,但它没有提供 ioctl() 争论的答案。然而,这表明需要 ioctl()
调用。
首先,TUN/TAP 接口被记录在案 in the Linux kernel documentation,如果您还没有看过它,值得一读。当然,示例是用 C 语言编写的,但希望仍然有用。
I see references to the second arguement being
TUNSETIFF
. All I know is that it has to be numeric. What is it asking for?
这是一个 C 库常量,您可以使用如下代码确定其值:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/if.h>
#include <linux/if_tun.h>
int main(int argc, char **argv) {
printf("TUNSETIFF: %d\n", TUNSETIFF);
return 0;
}
我的系统 returns:
TUNSETIFF: 1074025674
From what I've gathered, the third arguement is supposed to be flags of some sort, but I have not managed to find info on them. Presumably, one flag would be for selecting if it should be a Tun or Tap tunnel. Any info on this?
第三个参数是指向结构的指针,该结构具有
ifr_name
属性,包含设备名称和一个 ifr_flags
包含标志的属性。内核文档提供了
以下示例代码:
/* Flags: IFF_TUN - TUN device (no Ethernet headers)
* IFF_TAP - TAP device
*
* IFF_NO_PI - Do not provide packet information
*/
ifr.ifr_flags = IFF_TUN;
if( *dev )
strncpy(ifr.ifr_name, dev, IFNAMSIZ);
if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ){
close(fd);
return err;
}
您可以找到不同标志的值(IFF_TUN
、IFF_TAP
)
使用上面我们用来查找值的相同代码
TUNSETIFF
.
如果您正在用 Perl 编写代码,您将需要一种方法来创建 相应的 C 兼容结构。我的 Perl 太生锈了建议 我想到了正确的解决方案。
但是,似乎有许多可用的 Perl 模块 简化整个过程: