如何搭建自己的『暗网』
是的,你没有看错,暗网
一张在互联网上工作的,内容与互联网隔离的,高度加密的,需要特殊方式来加入的网络
前言
好吧,我承认,确实有那么一点点标题党的成分。但是这也是笔者的目的,因为在开始讲述之前,我想先扔出来这么一个问题:
你认为,暗网 等同于 Tor网络(下面就简称Tor)吗?
此处先按下不表,答案在下一小节揭晓。
在上次的那篇文章里笔者提到过,那个测试用的CMS搭建在『杏泉网络』上。本篇文章其实就是来聊一聊关于这个网络的事情。你要说杏泉网络成气候么,那不成,毕竟就我一个人玩。但是你说好玩么.....看个人吧,反正笔者比较喜欢这种玩法。
说白了,杏泉网络本质上是类似于DN42或者NeoNetwork,又或者是ChaosVPN之类的VPN网络,是跑在现成的互联网之上的一张网络。其设计目标是模拟真实的互联网(甚至这三张网络也是互联的),有意加入的人可以申请到一段v4和v6地址以及AS号(都在私有地址范围内),然后通过各种VPN和其他节点起Peer,配合各种IGP路由协议进行互联,然后就可以网内互访了。
从这段描述中你可以发现:这种网络更像是某种在线版的HackerSpace,设计目的并不是为了提供匿名性(当然实际实现中或多或少会有一定的匿名性,但是并非必然,也不能依赖于此),而是仅仅是作为一个试验场,一个任由你发挥的网络空间,或者用于无NAT网络互联——说白了,就是玩具,大号玩具。
关于暗网
现在可以回答刚刚那个问题了:Tor是暗网,但是暗网不等同于Tor。
因为Tor的使用占比大,而且也是最知名的暗网服务,导致很多人以为暗网就是Tor。但是如果我们回到暗网最基础的定义上来:只能通过特定软件、配置或授权,且通常使用独特的通信协议,才能访问的网络,很显然,你正在使用的QQ,微信,这些都是暗网,因为他们需要特殊软件配置和授权,而且QQ微信也有整自己的协议,可以说完美符合暗网的定义。此外还需要注意的一点是,严格来说,暗网不一定要存在于公共互联网上,对于一般访问者而言,朝鲜的光明网是暗网,古巴的Street Network是暗网,各大金融军政机关的网络也可以认为是暗网
在这篇博文里,笔者把暗网的定义收缩一下,让他比较符合直观中暗网的定义,这就是杏泉网络的主要特点:
- 依托互联网作为基础链路,在此之上强加密
- 需要特殊通信协议进入
- 内部有单独地址空间
- 有内部资源可供使用
如果你也按照这些思路来,说不好你也可以弄出来一个这样的.....玩具网络?
地址空间的规划
既然要搭建这样的网络,而且里面跑的是IP协议,怎么选择IP地址段自然是个学问。关于这一部分,可以阅读笔者关于VPN选型中讲述的内容,道理是一样的
不过里面没有提到的是IPv6地址空间,但是选择起来也不难。基于同样的理由,你可以选择使用:
- fd00::/8 (V6内网)
- 2001:db8::/32 (文档段)
来作为v6互联地址。
互联地址和业务地址
前段时间吧,当然其实一直以来都有,笔者在很多地方看到说,办理专线拿了IPv6却不会配,因为运营商给了两个地址,一个叫互联地址,一个叫业务地址,都在IPv6全球单播地址范围内(或者说互联地址在v6内网地址范围内),不知道怎么处理。
其实吧,理论上这才是网络的正确玩法,包括IPv4也是理论上也应该这么玩。只不过因为v4地址段严重短缺,很多用户拿不到自己的IP段,只能使用ISP分配的,也无法起路由协议,更加没办法给自己的内网设备分配公网IPv4地址(内网地址不可在公网路由,所以不必广播出去),才产生了『v4没有这玩意啊』的误解,只能用运营商给的互联地址兼做业务地址,然后里面再做NAT之类的操作。
在杏泉网络(包括其他类型的暗网)内就没有这个问题了,因为地址空间巨大,所以必须区分下这两个概念。简单来说,『互联地址』指的是两台路由器之间互联使用的地址,而『业务地址』则是两台路由器背后的设备所使用的地址。换句话说(包括刚刚那个V6的例子也是一样的),你应该把运营商给你的互联地址配置到路由器的互联口/WAN口,把业务地址配置到路由器的Loopback口,以及路由器下属设备的接口/Loopback口(如果你内部也有路由的话)。
链路的选择
想要把IP网络打通,这一部分就丰俭由人了,IKEv1,IKEv2,OpenVPN,WireGuard,Tinc之类的,都可以。简单玩玩的话,甚至你还可以使用VPNCloud,Tailscale,Zerotier之类的成品去中心化组网软件。笔者的话,考虑到后期可能想要对接别的路由协议,于是干脆用底层一点的WireGuard,配置起来简单快速,也可以充分发挥VPN作为『大号网线』的作用。IP网络通了之后,如果你想要玩二层互通,方案也有很多,L2TP,VxLAN,也是任君选择。
这里着重提一点关于链路的问题。两台机器互联,很自然而然都能想到用点对点网络。如果网络内的『路由器』没有Windows设备,那么笔者推荐在设备之间互联的时候,互联地址使用/31掩码,与传统的/30掩码相比,能够节约一大批IP,具体来说,一个C段就能开出来实打实的128对点对点链路,利用率高很多
当然你也注意到了,上面的协议可能不是很适合跨越大墙。笔者目前的思路是:如果你玩境外节点,那么就使用一台接近大陆地区的机器,作为边缘路由器,提供代理协议给自己的大陆机器接入——可能无法实现全链路互通,但总比没有好。不过这么干的话得注意合规性风险,笔者在此不做任何背书。如果你想要规避风险,最合适的方式是境内外隔离,单独分开网段,然后在访问端(例如你的软路由上)再做聚合
实操
以下内容假设你已经对WireGuard有一定的了解
作为例子,笔者准备了两台位于公网上的机器,一台香港,一台美国(因为目前就这俩),地址分配如下:
美国:
- 互联地址:198.18.0.0/31,fd04:17:0::0/127
- 业务地址:198.18.3.0/24,fd04:17:1:0000::/48
香港:
- 互联地址:198.18.0.1/31,fd04:17:0::1/127
- 业务地址:198.18.4.0/24,fd04:17:1:0001::/48
两台机器都是Debian 12,预先安装好WireGuard。安装WireGuard的过程在此略过,反正一条apt就装上了。安装好之后记得打开路由转发功能,IPv4和IPv6都要打开。如何打开?网上教程很多,这里不再赘述。
装好之后,先打开一台机器,比如us机,进入/etc/wireguard
,生成一个wg-hk-1
文件(因为WireGuard使用文件名作为接口名,命名为wg-hk-1就很直观能看到这个接口通往何处:香港1号机),然后在里面写入:
[Interface]
PrivateKey = <本机私钥>
Address = 198.18.0.1/31
Address = fd04:17:0::1/127
ListenPort = <监听端口>
# 因为之后还要对接别的路由协议,所以就不让WG自己添加路由了
Table = off
MTU = 1380
[Peer]
PublicKey = <香港机公钥>
# 如果Table不等于off,千万不要设置AllowedIPs为全0掩码
# 不然WG起来之后,路由表一动,你和机器的连接就被切断了
AllowedIPs = 0.0.0.0/0
AllowedIPs = ::/0
Endpoint = <香港机公网地址>
保存好,然后执行wg-quick up wg-hk-1
把接口开起来。下一步需要让这个命令开机后自动执行,用systemctl直接控制wg-quick当然可以,但是笔者决定偷个懒(也是为了更好操作),借助一下rc.local的力量(Debian 12默认停用了rc.local,如何重新启用,网上教程很多,这里不再赘述)。
打开/etc/rc.local
,在exit 0
之前添加:
wg-quick up wg-hk-1
ip addr add 198.18.3.1/24 dev lo # 业务地址要配到Loopback口上
ip -6 addr add fd04:17:1:0::1/48 dev lo # 业务地址要配到Loopback口上
# 实验演示,这里就不搞动态路由了,直接用静态
# 指向香港机器的业务地址,网关就是香港机器的互联地址
ip r a 198.18.4.0/24 via 198.18.0.1 dev wgxqnet-hk-1
ip -6 r a fd04:17:1:1::/48 via fd04:17::1 dev wgxqnet-hk-1
保存。然后再把上面的命令手动执行一下。
另一边,香港机器也是类似的处理方式,记得把密钥对,对端地址,业务地址,互联地址,路由,都设置正确。
测试
配好之后,你的暗网就搭建起来了,简单测试一下
# traceroute -n 198.18.3.1
traceroute to 198.18.3.1 (198.18.3.1), 30 hops max, 60 byte packets
1 198.18.3.1 150.013 ms 149.696 ms 149.747 ms
# traceroute -n fd04:17:1:0::1
traceroute to fd04:17:1:0::1 (fd04:17:1::1), 30 hops max, 80 byte packets
1 fd04:17:1::1 150.019 ms 149.902 ms 149.727 ms
如果你想在网内搭建服务,那么服务器软件只需要监听lo卡,或者说是本机业务地址就可以了。例如在us机上有nginx作如下配置:
server {
listen 198.18.3.1:80; //这里是关键
listen [fd04:17:1:0000::1]:80; //这里也是关键
server_name 198.18.3.1 [fd04:17:1:0000::1];
root /var/www/html;
index index.php index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
}
}
那么,在网内就可以访问到这个机器了。比如说目录里面有个php文件:
# curl 198.18.3.1
PHP is Working
DNS
如果你不想敲IP,那么DNS是个好选择。作为演示,就不弄DNS服务器了,采用hosts文件的方式来做域名解析
198.18.3.1 us.xq
fd04:17:1:0::1 us.xq
198.18.4.1 hk.xq
fd04:17:1:1::1 hk.xq
访问测试也是正常的:
# curl us.xq
PHP is Working
有什么用?
玩。
当然了,你可以在里面折腾一堆玩意,小到多出口代理(例如,做好安全措施之后,把默认路由指向网内某台机器,并打开NAT,就可以用那个机器出网),中到试验OSPF,BGP,TURN自动发现,Teredo隧道,4 over 6,QOTD服务,等等等等,一切你听过和没听过的协议,大到组建另一个『DN42』,让更多的朋友进来玩。限制你的只有想象力(当然可能还有你的钱包)。
写在最后
简单水一篇文章,最近结束了一单小活(做了个网站前后端),终于有时间更新博客了。
写在五一假期的结尾....呃,好像说『上班快乐』不太合适?
(完)