DDNS+IPV6实现外网访问
上网配置
之前一直是通过搭建在腾讯云上的FPR实现内网穿透,访问家里的设备,但这样也不是持久的办法。毕竟云服务器一年的费用让我非常肉痛,4核4g的云服务器我一次性购买了4年,花了四百多,然后一看续费,一年1400......,这坚定了我为NAS整一个IP地址的想法。
我按照网上的教程和联通运营商battle了几次,客服一直一副糊弄的态度,说什么也不给IP地址。
刚开始一直以为家里没有ipv6地址,在cmd命令行里用ipconfig
指令也获取不到IPV6地址。在一次偶然情况,越过路由器把网线插电脑上,直接用电脑进行拨号,发现获取到了IPV6地址,原来是路由器太老了,不支持IPV6协议。赶紧买了个支持IPV6协议的路由器,买的型号是京东的无线宝,一边当路由器,一边用闲置带宽挂积分,一天也能有个接近一块钱的收益。
将支持IPV6的路由器连接在光猫上,光猫改桥接,由路由器进行拨号,打开路由器IPV6开关,上网方式选择自动获取IP地址,关闭IPV6的防火墙。保存配置之后,路由器下的设备就都获取到了IPV6地址了。
获取到IPV6地址后可能还不能非常愉快的进行内网访问,因为运营商都会把敏感的端口例如443,80等端口封禁掉,这样在访问时要加上相应的端口号,使外网访问的地址看起来不是很正式,但也没有很好的办法了。
在支持IPV6的外网环境下,使用python代码扫描内网端口,发现 [53, 80, 135, 139, 443, 445, 593, 1062, 1569, 3175, 3669, 4444, 5293, 5554, 5791, 7375, 7850, 8080, 9515, 9955, 9995]等端口都被运营商封禁了,要把内网服务暴露到外网,只能使用这些之外的端口了。
import socket
def scan_port(target_host, target_ports):
filtered_ports = []
try:
# 解析域名获取 IPv6 地址
target_ip = socket.getaddrinfo(target_host, None, socket.AF_INET6)[0][4][0]
print(f"正在扫描 {target_host}({target_ip}) 的端口...\n")
for port in target_ports:
try:
sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
sock.settimeout(1)
result = sock.connect_ex((target_ip, port))
if result == 11:
print(f"端口 {port} 过滤")
filtered_ports.append(port)
sock.close()
except socket.error:
print(f"无法连接到主机 {target_host}")
break
except socket.gaierror:
print(f"无法解析域名 {target_host}")
return filtered_ports
target_host = "example.com"
target_ports = range(1, 10001)
filtered_ports = scan_port(target_host, target_ports)
# 输出被过滤的端口
print("被过滤的端口:", filtered_ports)
DDNS
我们通过拨号从运营商那获取的IPV6地址并不是一成不变的,每当光猫重启或者隔一段时间,IPV6地址就会改变。因此通过固定的ip地址访问是不可行的,这就要用到动态域名解析DDNS,绑定域名实现内网设备访问了。
DDNS GO是一款动态域名解析神器,提供友好的WEB界面进行操作。
docker安装DDNS-GO
mkdir -p ${path_docker}/ddns-go
docker run -d \
--restart=unless-stopped \
--name ddns-go-aliyun \
-e PUID=1000 \
-e PGID=100 \
-p <yourIP>:9876 \
-v ${path_docker}/ddns-go:/root \
jeessy/ddns-go \
-f 60
通过ip:9876
访问DDNS GO页面
DDNS GO配置
DDNS GO通过实时监测宿主机的ip地址和绑定域名解析的ip地址是否一致,一旦宿主机的ip地址发生改变,就通过DNS服务商提供的API对绑定域名的解析地址进行更新,保证解析到宿主机ip地址。
DDNS GO支持各家dns服务商,如阿里云、腾讯云以及cloudflare等。我使用的是腾讯云的DnsPod进行域名解析,首先需要进入DNSPod的控制台,创建一个API密钥,通过这个密钥可以自动添加DNS解析。
将获取的ID和token填入DDNS GO中,因为本地没有IPV4地址,所以选择不启用IPV4。在Domains中填入需要进行解析的域名,可以一次性填入多个域名,当打开公网访问时,需要设置用户名和密码,完成设置后,点击保存就会自动进行域名解析。
从日志中可以看出,每隔一段时间,DDNS GO就会检查本机地址和解析地址是否一致,保证解析地址的正确性。
NgnixProxyManager
Nginx proxy manager(NPM)是集Nginx设置和ssl证书申请的docker神器。
官方网站:https://nginxproxymanager.com/
通过DNS或者DDNS,我们打通了了域名到公网IP连接,Ngnix的作用是什么呢,通过建立一个反向代理服务器,他的作用是监听本地的ip地址的端口(如443和80端口),按设置拦截客户端的请求,并转发的宿主机相应的端口上,它可以决定将哪个域名的流量转发到哪一个服务器的端口,打通了公网IP到端口这个连接。
而NgnixProxyManager提供了一个Ngnix的可视化面板,可以有效地对反向代理服务器进行管理,并且还具有申请SSL证书的功能。
当然,通过宝塔面板也可以对Ngnix进行可视化操作,但是是将Nginx直接安装在宿主机上,对于非专业的用户,一旦安装的web应用过多,非常容易发生冲突,导致web无法被访问,而NgnixProxyManager将Nginx安装在docker容器中,利用了容器的隔离避免了误操作带来的软件版本冲突。
docker安装和直接部署两者各有各的好处,对于新手来说,安装在docker中更加省心,也易于迁移。
docker-compose安装
version: '3'
services:
app:
image: 'jc21/nginx-proxy-manager:2.9.18'
restart: unless-stopped
ports:
- '7080:80'#80被封禁所以修改
- '7081:81'
- '7443:443'#443被封禁所以修改
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
因为80、443端口被运营商封禁,所以这里进行了映射,如果是在VPS中,可不用进行修改。这个81端口是NPM的默认后台端口,这个你可以改一个自己喜欢的。我建议不要用默认的81端口,这样可以使NPM更加隐蔽。
服务管理
# 上线服务
docker-compose up -d
# 下线服务
docker-compose down
# 更新服务(我还没用过。更新的话建议先对旧服务进行备份,以防新旧版本有兼容问题。)
docker-compose pull
docker-compose up -d
不要忘了用在防火墙里开放你选择的NPM-后台端口
端口,开放端口后通过访问:http://<ip>:<NPM-后台端口>
进行NPM管理。
NPM的默认账号如下,在登录后可以自行进行修改。
默认帐户:admin@example.com
默认密码:changeme
在访问后web服务后,在登陆时可能存在Bad Gateway的问题。
在查看docker日志后发现,运行卡在Fetching https://www.cloudflare.com/ips-v4
这一步
上网一查cloudflare的ipv4和ipv6网段被宝塔面板屏蔽,访问ipv4和ipv6地址获取宝塔的网段,在宝塔中添加进白名单进行放行即可。
Cloudflare 官方公布IP段:
https://www.cloudflare.com/ips-v4
https://www.cloudflare.com/ips-v6
IPv4
173.245.48.0/20
103.21.244.0/22
103.22.200.0/22
103.31.4.0/22
141.101.64.0/18
108.162.192.0/18
190.93.240.0/20
188.114.96.0/20
197.234.240.0/22
198.41.128.0/17
162.158.0.0/15
104.16.0.0/13
104.24.0.0/14
172.64.0.0/13
131.0.72.0/22
IPv6
2400:cb00::/32
2606:4700::/32
2803:f800::/32
2405:b500::/32
2405:8100::/32
2a06:98c0::/29
2c0f:f248::/32
放行后就可以顺利登录NPM面板,对于需要代理的域名为example.com,设置其转发到172.17.0.1的4025端口,如果Nginx监听的是80和443端口,这样example.com:80/443的所有流量就会转发到172.17.0.1:4025,在访问的时候就会自动隐去端口号,显得域名更加正式。
在SSL菜单中,可以为域名添加SSL证书实现HTTPS访问,由于家庭宽带的80和443端口是被封锁的,所以用http challenge申请ssl证书的方式很容易失败。在Nginx proxmy manager中,对于NAS用户推荐使用DNS challge的方式来申请Let’s Encrypt证书。我选择的是DNSPod进行域名解析,id和key申请在上面DDNS GO中也进行说明,直接填入就行。
我一般喜欢统一申请好二级域名证书(只为leiting2020.top
申请1个证书),然后在建立新的反向代理记录后添加申请好的二级域名证书,要同时为两个域名申请*.leiting2020.top
、leiting2020.top
(*
是一种常用的正则表达式,用来代表所有字符),这样才可以正常使用。
多数docker应用可以通过这样简单地设置即可以实现成功代理。
通过上述配置,这样就可以为IPV6地址的NAS解锁外网访问,需要注意的是,如果NAS只有IPV6地址,建立的网站就是纯IPV6网站,在纯IPV4网络环境中是无法进行访问的,通过IPv6 测试 (test-ipv6.com)测试当前网络环境是否支持IPV6。
有一种方法也可以实现纯ipv4环境访问ipv6网页,那就是将域名挂载在cdn中,开启回源鉴权,这样可以实现ipv4访问,国内的dns厂商都不提供免费的ipv6 cdn,而且还将ipv4和ipv6分开进行计费。这样还不如白嫖cloudflare的免费cdn,将域名挂在cloudflare上,点亮小云朵就可以白嫖cloudflare的免费cdn。
不过cf的免费cdn主机都不在国内,使用起来可能还是降速,而且对于家用NAS来说,443和80端口被封锁,配置cdn变得比较麻烦,我最终还是放弃了。