像玩樂高一樣玩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裏都寫了:
在這裏插入圖片描述
這裏的關鍵就幾行代碼:

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而登峯造極…


浙江溫州皮鞋溼,下雨進水不會胖。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章