我正在编写一个通过接口发送数据的程序tun
。我正在尝试向世界发送 IP 数据包。我的所有 TCP/IP 堆栈都在工作:它创建了一个准备发送的有效 TCP/IP 数据包,我只需要发送它即可。
我知道如何创建一个tun
接口,但是如何让这个 tun 接口将 IP 数据包中继到世界并接收它们呢?
我想发送连接到 google.com 的 IP 数据包并接收 HTTP 响应。
更新。在 Hauke Laging 的回答之后,我尝试了:
user@orwell2:~$ sudo route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.137.0.5 0.0.0.0 UG 0 0 0 eth0
10.137.0.5 0.0.0.0 255.255.255.255 UH 0 0 0 eth0
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0
user@orwell2:~$ sudo nano /etc/sysctl.conf
user@orwell2:~$ sudo sysctl -p
fs.inotify.max_user_watches = 524288
net.ipv4.ip_forward = 1
user@orwell2:~$ sudo openvpn --mktun --dev tun1 --user $USER
Tue May 26 18:45:09 2020 TUN/TAP device tun1 opened
Tue May 26 18:45:09 2020 Persist state set to: ON
user@orwell2:~$ sudo ip link set tun1 up
user@orwell2:~$ sudo ip addr add 192.168.0.2/24 dev tun1
user@orwell2:~$ sudo iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
user@orwell2:~$ sudo iptables -A FORWARD -i tun1 -o eth0 -j ACCEPT
user@orwell2:~$ ping -I tun1 google.com
PING google.com (172.217.28.238) from 192.168.0.2 tun1: 56(84) bytes of data.
^C
--- google.com ping statistics ---
7 packets transmitted, 0 received, 100% packet loss, time 6179ms
user@orwell2:~$ sudo iptables -t nat -nvL POSTROUTING
Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 MASQUERADE all -- * !docker0 172.17.0.0/16 0.0.0.0/0
0 0 ACCEPT all -- * vif+ 0.0.0.0/0 0.0.0.0/0
6 312 ACCEPT all -- * lo 0.0.0.0/0 0.0.0.0/0
102 6268 MASQUERADE all -- * * 0.0.0.0/0 0.0.0.0/0
正如你所看到的,我无法ping google.com
通过tun1
。然后我打印了伪装选项,但我不知道是否需要添加一个tun1
。
答案1
我相信您需要在您正在创建的隧道设备上设置正确的本地和远程地址,以便将您的程序创建的数据包中继到全世界。
根据提供的 PCAP 文件,您的程序生成来自地址 的 TCP/IP 数据包192.168.69.1
。那应该是 TUN 设备的远程地址。我的建议是创建隧道设备并设置 IP 转发和主机防火墙,如下所示:
$ sudo ip tuntap add dev tun1 mode tun user `id -un`
$ sudo ip link set dev tun1 up
$ sudo ip addr add dev tun1 local 192.168.69.0 remote 192.168.69.1
$ sudo iptables -t filter -I FORWARD -i tun1 -o eth0 -j ACCEPT
$ sudo iptables -t filter -I FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
$ sudo iptables -t nat -I POSTROUTING -o eth0 -j MASQUERADE
$ sudo sysctl net.ipv4.ip_forward=1
$ /path/to/your/packet/generator/program tun1
在古代,当人们将调制解调器设备连接到电话线并拨打互联网提供商的电话以建立与互联网的连接时,pppd
守护进程通常负责与位于的服务器建立点对点隧道。在通话的另一端。在这些隧道上,本地地址是分配给在内核网络堆栈中创建的网络接口的地址,远程地址是应答电话呼叫的另一台计算机的本地地址,也是在隧道中设置为默认网关的地址。本地方面。
对于 TUN 虚拟设备,您的用户空间程序将充当隧道另一边的远程计算机。因此,为了让程序将 IP 数据包注入内核网络堆栈,程序应该生成源地址设置为隧道远程地址 ( 192.168.69.1
) 的数据包,并接收目的地设置为相同地址的数据包。
答案2
您必须在系统上配置路由和(也许)数据包过滤器(防火墙)。
- 设置
net.ipv4.ip_forward
为 1(sysctl
用于永久配置) 如果防火墙还不允许转发,那么你需要类似的东西
iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT iptables -A FORWARD -i tun0 -o eth0 -j ACCEPT
您可能还需要 MASQUERADING/SNAT,以便您的网关知道数据包来自该系统(请参阅 参考资料
iptables -t nat -nvL POSTROUTING
)