一、概述
如文章标题所示,作者的目标是实现对家庭局域网的安全访问,从而可以对局域网中的主机进行文件访问、远程桌面等操作。
作者的宽带是移动宽带,可获取公网Ipv6地址,作者的路由器之一是红米AX3000。实际上在关闭光猫和红米AX3000的Ipv6防火墙后,即可对局域网设备进行访问了。但是这样设置,存在极大的安全隐患,内网设备的Ip和端口完全暴露于公网,给了攻击者攻击的机会。
作者的另一个路由器是小米路由器4A千兆版。作者将此路由器刷成LEDE(openwrt)系统,在其上配置防火墙规则、DDNS和OpenVPN服务器,使得手机可以通过OpenVPN隧道连接此路由器并访问局域网。此外在手机上安装WOL软件可唤醒局域网中的主机。
虽然路由器对于数据包的转发能力很强,但对于数据的加密能力不强(个人猜测),所以不论手机是使用流量还是使用路由器的WiFi来连接OpenVPN服务器,文件下载的速度都很慢,仅2.5MB/s,对路由器的远程管理或者对主机的远程桌面,这个速度是足够的。但是对于文件传输来说就太慢了,试想一个100MB的文件需要40秒,这无法让人接受。
在上述搭建的环境的基础上,作者通过OpenVPN远程登录自己的主机,在自己主机上运行V2Ray服务器,在路由器设置相关转发规则,然后用手机通过V2Ray隧道连接自己的主机。通过这条隧道,一样可以对局域网进行访问。在手机使用路由器WiFi的情况下,文件下载速度达到40MB/s,但是使用流量时不到2MB/s,而此宽带的上行带宽可达130Mbps。后续,作者借了一部5G手机,测得使用WiFi时下载速度可达80MB/s,使用流量下载速度可达20MB/s。
网络
家庭网络拓扑图如下,其中红米AX3000保持Ipv6防火墙开启,除主机外的设备都通过AX3000上网。
如下图,在LEDE上运行OpenVPN服务器,使用ifconfig命令可以看到多出了名为tun0的接口,ip为10.0.8.1,它的功能和lan接口相同,即作为一个局域网的网关,不同在于tun0是由纯软件实现的。手机使用OpenVPN客户端经由互联网连上OpenVPN服务器后,客户端会被分配一个虚拟ip地址,如10.8.0.10,在逻辑上手机成为了tun0局域网的一员。在LEDE配置转发规则,允许这两个局域网互相通信,则手机可访问主机。
如下图,在主机运行V2Ray服务器,在LEDE配置转发规则,允许将WAN口数据包转发到V2Ray服务器。在V2Ray服务器配置入口出口规则,可实现手机访问主机、局域网甚至互联网。
Ipv6测试
在进入后续章节的搭建详细步骤前,先测试下,手机能否经由互联网使用Ipv6地址访问到局域网。
- 关闭光猫的Ipv6防火墙
中国移动的光猫管理员账号密码一般为CMCCAdmin,aDm8H%MdA。
取消勾选Ipv6Spi,将允许WAN口Ipv6数据包入站。
端口绑定,被勾选的端口允许上网。同时,在其他“连接名称”中不要绑定这里勾选的端口。
- 关闭AX3000的Ipv6防火墙,将主机连接在AX3000上。如果没有能够关闭防火墙的路由器,则直接将主机连接到光猫上。
在“常用设置”->“上网设置”->“IPV6网络设置”中关闭防火墙。注意,这会使设备暴露于公网,记得及时开启防火墙。
- 在主机运行http服务器。
使用终端工具进入主机的某一空白目录,运行python -m http.server。然后使用手机浏览器通过流量访问[主机Ipv6地址]:8000,若能访问到目录文件,则证明Ipv6通路。(记得及时开启防火墙)
二、LEDE系统
本节介绍将小米路由器4A千兆版刷写LEDE系统的过程。LEDE系统是OpenWrt的分支,功能比OpenWrt更丰富。OpenWrt基于Linux系统,一般路由器都基于OpenWrt系统进行开发。如果希望刷写OpenWrt系统,可访问[OpenWrt Wiki] 硬件列表:固件下载,下载下图所示的bin文件。
编译LEDE系统
准备一Linux环境,作者使用的是Debian发行版,运行下列命令行。编译lede项目要求使用非root用户;项目编译过程会下载GitHub和其他一些国外网站的数据,需要保持网络通畅;编译耗时约20分钟。
apt update -y
apt full-upgrade -y
apt install -y ack antlr3 asciidoc autoconf automake autopoint binutils bison build-essential \
bzip2 ccache cmake cpio curl device-tree-compiler fastjar flex gawk gettext gcc-multilib g++-multilib \
git gperf haveged help2man intltool libc6-dev-i386 libelf-dev libglib2.0-dev libgmp3-dev libltdl-dev \
libmpc-dev libmpfr-dev libncurses5-dev libncursesw5-dev libreadline-dev libssl-dev libtool lrzsz \
mkisofs msmtp nano ninja-build p7zip p7zip-full patch pkgconf python2.7 python3 python3-pyelftools \
libpython3-dev qemu-utils rsync scons squashfs-tools subversion swig texinfo uglifyjs upx-ucl unzip \
vim wget xmlto xxd zlib1g-dev python3-setuptools
adduser lede_user
cd /
su lede_user
git clone --depth=1 --single-branch https://github.com/coolsnowwolf/lede.git
cd /lede
./scripts/feeds update -a
./scripts/feeds install -a
make menuconfig
make download -j8
make V=s -j32
make menuconfig命令用于设置编译配置,下图列出了作者的部分编译选项。
编译出的包的路径为
/lede/bin/targets/ramips/mt7621/openwrt-ramips-mt7621-xiaomi_mi-router-4a-gigabit-squashfs-sysupgrade.bin。
刷写LEDE系统
在小米路由器管理界面的升级选项卡中,有选择固件进行手动升级的选项。但是作者没试过通过这种方式刷写OpenWrt或LEDE系统,所以不知道能否刷写成功。
作者使用了acecilia/OpenWRTInvasion: Root shell exploit for several Xiaomi routers: 4A Gigabit, 4A 100M, 4, 4C, 3Gv2, 4Q, miWifi 3C... (github.com)介绍的方法,首先打开路由器的ssh登录,然后上传并用命令行刷写的bin文件。
git clone --depth=1 --single-branch https://github.com/acecilia/OpenWRTInvasion.git
cd OpenWRTInvasion
pip3 install -r requirements.txt # Install requirements
python3 remote_command_execution_vulnerability.py # Run the script
使用上面的命令打开ssh后,提示可以用telnet、ftp或ssh连接路由器。将ftp路径复制到Windows资源管理器,将bin文件复制到/tmp目录下。打开终端,执行下列命令刷写LEDE系统。
ssh root@[路由器ip]
cd /tmp
mtd -e OS1 -r write openwrt-ramips-mt7621-xiaomi_mi-router-4a-gigabit-squashfs-sysupgrade.bin OS1 # Install OpenWrt
之后若要再次刷写bin文件,可通过升级选项卡上传bin文件并刷写。
启动LEDE系统后,配置或问题
- 登录密码:password。如果不是,在网上搜索一下。
- 刷写完后,路由器的WiFi很可能是开着的,且没有密码,记得及时关闭WiFi或设置密码。
- 在“网络”->“接口”中WAN6极可能显示不支持协议之类的提示,点击安装luci-proto-ipv6。
- 按下图配置LAN接口。
- 修改“网络”->“接口”中LAN,在“基本设置”中将IPv4地址修改为
192.168.200.1。 - 可将DNS服务器设为
223.5.5.5,速度会快些。
三、配置OpenVPN访问家庭局域网
OpenVPN服务器需要五个文件ca.crt,server.crt,server.key,dh2048.pem和server.conf,在LEDE上server.conf通过界面配置。客户端需要ca.crt,client.crt,client.key和client.conf,这四个文件的内容可以合并到一个client.ovpn文件中。
ca.crt是证书颁发机构的证书,服务器和客户端上存有相同的ca.crt,双方在确认彼此的证书时,需要ca.crt来验证。验证成功后,建立加密隧道。
在Debian上配置并运行OpenVPN
安装OpenVPN:
apt install openvpn
使用OpenVPN示例中的密钥和证书。后续小节将介绍密钥和证书的生成过程和在LEDE上的配置OpenVPN。
/usr/share/doc/openvpn/examples/sample-keys/ca.crt
/usr/share/doc/openvpn/examples/sample-keys/server.crt
/usr/share/doc/openvpn/examples/sample-keys/server.key
/usr/share/doc/openvpn/examples/sample-keys/dh2048.pem
/usr/share/doc/openvpn/examples/sample-config-files/server.conf
/usr/share/doc/openvpn/examples/sample-keys/client.crt
/usr/share/doc/openvpn/examples/sample-keys/client.key
/usr/share/doc/openvpn/examples/sample-config-files/client.conf
将服务器需要的五个文件拷贝到/etc/openvpn,server.conf文件的内容如下:
local :: # 监听所有Ipv6地址
port 1194
proto udp
dev tun
ca ca.crt
cert server.crt
key server.key # This file should be kept secret
dh dh2048.pem
server 10.8.0.0 255.255.255.0 # tun0局域网的ip地址范围
ifconfig-pool-persist /var/log/openvpn/ipp.txt
keepalive 10 120
persist-key
persist-tun
verb 3
运行openvpn;
cd /etc/openvpn
openvpn --config server.conf
输出下面的内容,则表示启动成功;
......
......Initialization Sequence Completed
创建client.ovpn文件,按照下列格式将客户端需要的4个文件内容复制到文件中;
client
dev tun
proto udp
remote xx:xx:xx::x # 替换为路由器的公网Ipv6地址或域名(需设置DDNS)
resolv-retry infinite
nobind
persist-key
persist-tun
cipher AES-256-CBC
verb 3
route-nopull
route 192.168.200.0 255.255.255.0 vpn_gateway # 手机访问这个网段,要经由VPN,否则不经过VPN
<ca>
-----BEGIN CERTIFICATE-----
# insert base64 blob from ca.crt
-----END CERTIFICATE-----
</ca>
<cert>
-----BEGIN CERTIFICATE-----
# insert base64 blob from client1.crt
-----END CERTIFICATE-----
</cert>
<key>
-----BEGIN PRIVATE KEY-----
# insert base64 blob from client1.key
-----END PRIVATE KEY-----
</key>
配置LEDE上的OpenVPN服务器
如图点击“修改”;
上传文件;
“高级配置”中设置监听的地址为::,应用修改,启动OpenVPN服务器。
配置LEDE上的防火墙
解读:
- “基本设置”中的“入站”指到达路由器的数据包,涵盖目的地为路由器或其他区域的数据包(即“入站”包含“转发”)。
- “拒绝”意为着路由器会回复“Refused”消息,而“丢弃”,路由器不会响应,建议使用“拒绝”的地方都使用“丢弃”。
- “入站”相当于总闸,若选为“拒绝”或“丢弃”,则“通信规则”里的设置是没有效果的。因此需设为“接受”。然后在“通信规则”里,添加如图所示的两条规则,因为当匹配到一条规则,后续规则就不会继续匹配了,所以这两条规则能够仅允许“目的地为路由器的公网Ipv6地址和1194端口的数据包”进站。
- 修改vpn区域,允许路由器将数据包从vpn区域转发到lan区域,以及从lan区域转发到vpn区域,即
10.8.0.0/24和192.168.200.0/24互通。
配置LEDE上IP/MAC绑定
在“网络”->“IP/MAC”绑定中,输入主机的MAC地址和ip地址192.168.200.55,接口选择br-lan。则主机将被分配静态ip地址。
配置安卓客户端,访问个人主机
将client.ovpn中的remote语句地址改为路由器的公网Ipv6地址,在下一节配置好DDNS后,再改为域名。
将文件复制到手机,在OpenVPN Connect软件中导入此文件,点击连接,应显示为绿色。
测试:见前文,运行http服务器,手机浏览器访问192.168.200.55:8000,应当可以访问。
配置DDNS
解读:
路由器周期性地使用
nslookup查询第一张图中“查询主机名”得到Ipv6地址a,路由器WAN口Ipv6地址为b,当a和b不相同时,路由器将更新第一张图中的“域名”的解析。假设购买的域名为example.com,则第一张图中的“查询主机名”和“域名”都设为xxx.example.com,xxx可以任取。
作者在阿里云上租的域名,这里用户名和密码为RAM用户的access key和secret key。访问RAM 访问控制 (aliyun.com),创建RAM用户,并创建一对ak/sk。创建如下权限策略,并授权给RAM用户。此外需要预先在阿里云上添加将xxx.example.com解析为Ipv6地址的记录。
{
"Version": "1",
"Statement": [
{
"Effect": "Allow",
"Action": [
"alidns:DescribeSubDomainRecords",
"alidns:UpdateDomainRecord"
],
"Resource": [
"acs:alidns:*:用户ID:domain/二级域名",
// 例如:"acs:alidns:*:111111122222:domain/example.com",
]
}
]
}
生成密钥和证书文件
在Debian环境中,
cd /usr/share/easy-rsa
./easyrsa init-pki
./easyrsa build-ca --keysize=3072 # 生成ca.key,ca.crt
./easyrsa build-serverClient-full xxx-server nopass # 生成xxx-server.key,xxx-server.crt
./easyrsa gen-dh # 生成dh.pem
./easyrsa build-serverClient-full xxx-client nopass # 生成xxx-client.key,xxx-client.crt
四、配置V2Ray访问家庭局域网
在个人主机配置服务器端,监听手机客户端请求
{
"inbounds": [
{
"port": 1201,
"protocol": "vmess",
"settings": {
"clients": [
{
"id": "XXXXxxxx-XXXX-XXXX-XXXX-XXXXxxxxXXXX",
"level": 1,
"alterId": 64
}
]
}
}
],
"outbounds": [
{
"protocol": "blackhole",
"settings": {}
},
{
"protocol": "freedom",
"settings": {},
"tag": "freedom"
}
],
"routing": {
"rules": [
{
"type": "field",
"ip": [
"192.168.200.55",
"192.168.200.1"
],
"outboundTag": "freedom"
}
]
}
}
解读:
- 入站连接类型一种,id为密码,可通过
v2ray.exe uuid随机产生。 - 出站连接类型两种,第一种为默认出站类型,凡是没有在routing匹配到规则的入站数据包,都通过第一种类型出站。所以上述配置仅允许转发vmess入站且目的地为给定的两个ip的数据包。
新建run.bat文件,内容如下,点击即可运行:
v2ray.exe -c server.json
客户端配置
{
"inbounds": [
{
"port": 10808,
"listen": "127.0.0.1",
"protocol": "socks",
"settings": {
"udp": true
}
},
{
"port": 10809,
"listen": "127.0.0.1",
"protocol": "http",
"settings": {
"udp": true
}
}
],
"outbounds": [
{
"protocol": "freedom"
},
{
"protocol": "vmess",
"settings": {
"vnext": [
{
"address": "",
"port": 1201,
"users": [
{
"id": "XXXXxxxx-xxxx-xxxx-xxxx-XXXXxxxxXXXX",
}
]
}
]
},
"tag": "vmess_tun_to_mypc"
}
],
"routing": {
"domainStrategy": "IPOnDemand",
"rules": [
{
"type": "field",
"ip": [
"192.168.200.55",
"192.168.200.1"
],
"outboundTag": "vmess_tun_to_mypc"
}
]
}
}
解读:
客户端,如手机,入站规则两种,默认出站规则是直连,当目标为给定的两个ip时,通过vmess出站发往主机。
address改为主机Ipv6地址,id与服务器端一致。将配置导入手机V2RayNG软件中。
添加LEDE防火墙规则
允许公网访问主机的Ipv6地址的1201端口。
测试手机能否访问主机
使用前文所述的方法开启http服务器进行测试。注意主机的Ipv6经常变化,一旦变化就需要修改防火墙和客户端配置中的地址。另一种方法时使用端口映射,即凡是访问路由器某端口的数据包都转发到主机的某端口。端口映射对Ipv6来说并不常见,路由器页面上仅ipv4支持,网上搜索结果最多的是使用名为socat的软件来实现。
(完)