像玩乐高一样玩simpletun

netcat小巧而灵活,能应付各种你需要的网络测试。

但要明白netcat所能应对的网络场景基本都和端到端有关,比如和TCP,UDP有关。

网络还有另一面,即链路本身。如果你想模拟一个防火墙,模拟一个NAT怎么办?用netcat能做到吗?这个时候你可能就必须自己写内核模块了吧。

Netfilter?eBPF?NFV?这些都太复杂了!

可以在用户态完成的时候就尽量在用户态搞,简单稳定最重要。

我推荐simpletun。

simpletun并不是某个著名的开源软件,但是在网上一找可以找一大片,随便找一个杂耍即可。我说的simpletun模拟搭建网络设备的功能并不是说用它的二进制直接就能做到,而是说你可以随意对它进行三两行的那种魔改,让它实现你需要的功能。

搭建一个TCP隧道我这里就不说了,详见:
https://github.com/marywangran/simpletun/blob/main/simpletun.c

本文我要演示一个NAT功能。

正好我要调研一个NAT64的方案,我在思考如果没有现成方案的话能不能用tun设备搭建一个,当然了,肯定是有现成方案的,也就没有动用tun设备。但总想试试,看看到底有多简单,那就简单写了一个:
https://github.com/marywangran/simpletun/blob/main/tunnat.c

玩法很简单,README里都写了:
像玩乐高一样玩simpletun_第1张图片
这里的关键就几行代码:

if (FD_ISSET(tap_fd, &rd_set)) {
     
	struct iphdr *iph;
	/* data from tun/tap: just read it and write it to the network */
	unsigned int addr1 = inet_addr(from_ip);
	unsigned int addr2 = inet_addr(to_ip);

	nread = cread(tap_fd, buffer, BUFSIZE);
	iph = (struct iphdr *)buffer;
	if (addr2 == iph->daddr) {
     
		iph->daddr = addr1;
	} else if (addr1 == iph->saddr) {
     
		iph->saddr = addr2;
	} else {
     
		continue;
	}
	iph->check = 0;
	iph->check = ip_checksum((unsigned short *)iph, 20);

	nwrite = cwrite(tap_fd, buffer, nread);
}

当然,如果你想实现一个完整可用的NAT,那肯定需要维护一些链表保存session之类,但POC不需要这些。

相对应的,如果你想用tun模拟一个NAT64,也并不困难:

  • 将需要被NAT64的流量路由到tun网卡。
  • 用你的程序将从tun字符设备读取的裸包IPv4头换成IPv6头。
  • 将换完的裸包作为buffer写回到tun字符设备。

额外在外部配合一些个配置即可,这些配置基本上用iproute2都可以完成。

simpletun的确很low,就像netcat和nginx相比也很low一样,问题是你需要拿它做什么。我之所以善于在很短的时间验证一个事情行还是不行,在于我不善于折腾复杂的东西。我一向的观点就是,如果我是一个画家,我希望拿起笔来作画,而不是去学那些复杂的工具。

到底很多领域的所谓牛人是在该领域真的很牛呢还是说作为活体说明书很牛呢?很多的优秀设计师因为不会CAD找不到工作,也有很多的菜鸟设计师因为精通CAD而登峰造极…


浙江温州皮鞋湿,下雨进水不会胖。

你可能感兴趣的:(simpletun,NAT)