c-向目标服务器发送tun/tap数据包



如何将读取的数据包从tun发送到服务器?我通过Wireshark检查了数据包,所有的数据包都是DNS请求,并将系统的默认网关更改为VM的IP,所有数据包都会到达那里。tun运行良好,我可以打印有关数据包的所有信息,但问题是我不知道如何将它们转发到目标服务器。(我知道套接字编程(
代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <netdb.h>
#include <fcntl.h>
#include <signal.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#include <linux/ip.h>
#include <arpa/inet.h>
#include <netinet/in.h>
struct sockaddr_in Packet, dest;
#define Tun_Device "tun0"
static int max(int a, int b){
return a > b ? a : b;
}
int read_tun(char *name, int type){
struct ifreq ifr;
int tun_fd;
tun_fd = open("/dev/net/tun", O_RDWR)
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = type;
strncpy(ifr.ifr_name, name, IFNAMSIZ);
ioctl(tun_fd, TUNSETIFF, (void *)&ifr);
return tun_fd;
}
int main(){ 
int tun_fd, packet_length, tcpfd;
struct sockaddr_in cliaddr, servaddr;
char buffer[2048];
char destination[16];
int i = 0;
struct iphdr *iph = (struct iphdr*) buffer;
tun_fd = read_tun(Tun_Device, IFF_TUN | IFF_NO_PI);
while (1) {
fd_set readset;
FD_ZERO(&readset);
FD_SET(tun_fd, &readset);
FD_SET( , &readset);
int max_fd = max(tun_fd, udp_fd) + 1;
select(max_fd, &readset, NULL, NULL, NULL)
if (FD_ISSET( , &readset)) {
}
if (FD_ISSET( , &readset)) {
}
}
}

默认网关必须激活IP转发,并且需要设置相应的iptables规则。

从网关机器,您需要:

# Turn on IPv4 forward
sudo sysctl net.ipv4.ip_forward=1
# Add MASQUERADE rule
iptables -t nat -I POSTROUTING -s x.x.x.x/y ! -o tun0 -j MASQUERADE
# Allow forwarding
iptables -t filter -I FORWARD -d x.x.x.x/y -j ACCEPT
iptables -t filter -I FORWARD -s x.x.x.x/y -j ACCEPT
iptables -t filter -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT

备注

  • 使用TUN/TAP网络子网调整x.x.x.x/y
  • 使用您使用的虚拟网络接口名称调整tun0

客户端的默认网关设置

当您覆盖虚拟网络接口的任何流量时,您仍然需要与您的互联网路由器通信,因为您需要将封装的数据包发送到VPN服务器。

为了做到这一点,你不应该删除通过物理路由器的默认路由。

规则很简单:

  • 目的地/来源为VPN服务器IP地址的数据包必须通过物理路由器发送/接收
  • 其他数据包必须通过虚拟网络接口发送/接收
  • 另外,如果您有本地网络的话,您可能需要对其进行一些例外处理

配置示例

VPN_IFACE=tun0
VPN_PRIVATE_IP=10.8.8.2
VPN_GATEWAY_IP=10.8.8.1
VPN_BROADCAST_IP=10.8.8.25
VPN_PUBLIC_IP=123.123.123.123
REAL_DEFAULT_IP=192.168.1.1
# Raise up virtual network interface
sudo ip link set dev $VPN_IFACE up mtu 1480
sudo ip addr add dev $VPN_IFACE $VPN_PRIVATE_IP/24 broadcast $VPN_BROADCAST_IP
# Encapsulated packet must be routed via your real router.
sudo ip route add $VPN_PUBLIC_IP/32 via $REAL_DEFAULT_IP
# Override any traffic, except for encapsulated packet
# Make them routed via virtual network interface gateway
sudo ip route add 0.0.0.0/1 dev $VPN_IFACE via $VPN_GATEWAY_IP
sudo ip route add 128.0.0.0/1 dev $VPN_IFACE via $VPN_GATEWAY_IP
# Don't delete default route to your real physical router!

最新更新