作者 | dog250    责编 | 张文

出品 | CSDN(ID:CSDNnews)

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 里都写了:

这里的关键就几行代码:

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 而登峰造极…

程序员如何避免陷入“内卷”、选择什么技术最有前景,中国开发者现状与技术趋势究竟是什么样?快来参与「2020 中国开发者大调查」,更有丰富奖品送不停!



☞程序员硬核“年终大扫除”,清理了数据库 70GB 空间☞一行代码没写,凭啥被尊为“第一位程序员”?
☞任正非就注册姚安娜商标道歉;人人影视字幕组因盗版被查;JIRA、Confluence 等产品本月停售本地化版本 | 极客头条

Logo

20年前,《新程序员》创刊时,我们的心愿是全面关注程序员成长,中国将拥有新一代世界级的程序员。20年后的今天,我们有了新的使命:助力中国IT技术人成长,成就一亿技术人!

更多推荐