最近在家中搭建了一个文件服务器,之后想要试着从外网访问,才发现目前搭建公网服务的条件不是很好满足。打电话给电信客服,了解到获取公网IPv4地址的两种方式:
- 升级到399套餐,可以拿到公网IPv4地址
- 申请静态IPv4地址,月租费3000
这两种方案太花钱,当然是不能采纳了。幸好客服补充了一句,现在用户终端都是有IPv6公网地址的。从这句话出发,经过一阵折腾,终于实现了外网访问内网服务。由于涉及的点比较多,也踩了一些坑,接下来将把搭建网络的全过程做一个归纳总结。
方案的组网方式如下:
光猫需要接软路由R2S的WAN口,R2S的LAN口接入家里原来的Wi-Fi路由器。家里所有需要接入网络的设备配置不需要做任何改变。
软路由的LAN地址为192.168.100.1
,它给Wi-Fi路由器分配的地址为192.168.100.139
。内网的文件服务器地址为192.168.0.114:5085
。
当外网要访问这个服务器时,流程为:
外网用户使用域名加端口号访问服务 --> 域名服务器返回R2S软路由WAN口的IPv6地址 --> 外网用户访问此地址 --> 软路由将IPv6地址转化为IPv4地址,转发到Wi-Fi路由器 --> Wi-Fi路由器再转发报文到服务器。
采用这个方案的原因是:既利用了电信的公网IPv6资源,同时又保持了家里设备的IPv4地址设置不变。另外一个方案是家里的设备都获取IPv6地址,软路由不再做v6到v4地址的转换。但是我个人还是比较喜欢前一种方案,因为想家里设备尽量使用IPv4地址。
接下来对每个步骤做详细说明。
首先检查R2S软路由的WAN口设置,如果是直接获取IP地址,那么说明拨号是在光猫上进行的,IPv6地址并没有分配到路由器上。这时可以直接给电信客服打电话,要求把光猫改成桥接模式。这个会立即生效,之后重启软路由。重新配置WAN口,改为PPPoE方式,填上电信开网时提供的用户名和密码。拨号成功后,软路由的web管理界面不一定会显示WAN口的IPv6地址,这时可以ssh到软路由上,使用以下命令查看:
ifconfig -a pppoe-wan
如果在输出中看到类似240e
开头的IPv6地址,就表示软路由上已经有公网IPv6地址了。
Wi-Fi路由上,不需要做任何地址配置修改。只是需要检查一下WAN口配置,设置为自动获取IP地址即可。
因为希望IPv6地址一旦进入软路由后,所有的后继操作都转换成IPv4地址,因此需要在软路由上做地址转换。更新软路由的软件仓库,下载工具socat
,接下来在软路由终端上执行以下命令:
socat TCP6-LISTEN:5085,ipv6-v6only=1,reuseaddr,fork TCP4:192.168.100.139:5085
这条命令执行的是:当软路由监听到来自外部IPv6地址并且是对5085端口发起的连接请求时,对它进行IPv4地址的转换,使它转换成对192.168.100.139:5085
的连接访问。而这个地址正是软路由分配给Wi-Fi路由器的地址,因此数据会被转发到下一级路由器上。
可以把这条命令加到软路由的启动项里。在系统 --> 启动项 --> 本地启动脚本里,添加上面的命令,并在末尾加上'&'
以使命令在路由器启动后在后台运行。
默认的,路由器会拒绝外网发起的数据请求,因此需要在软路由上为进入的数据包放行。从安全的角度考虑,路由器上不要设置为WAN口默认接受所有外来数据请求,而是应该只对需要访问的数据包放行。
在软路由的网络 --> 防火墙 --> 通信规则中,增加一条规则以打开端口5085。在我的路由器中它的设置为:
由上面的socat
命令,数据已经完成了从软路由到Wi-Fi路由器转发,软路由上不再需要配置端口转发。在Wi-Fi路由器上,增加一条端口转发规则,将5085的数据转发到文件服务器192.168.0.114:5085
即可。
我是在noip上申请的域名。好处是申请免费,不过需要每30天激活一次。网站会发送提醒邮件,点击链接就完成了激活。也可以花钱去掉每个月激活的步骤。
在网站注册登录后,通过左边的导航条Dynamic DNS --> No-IP Hostnames,点击右面页面的'Create Hostname'开始创建一个域名。注意在申请过程中要勾选对AAAA记录,也就是IPv6的支持。填写IPv4和IPv6地址可以先随便填写一个,随后我们会在软路由上通过ddns来更新地址。
由于软路由上的公网IPv6地址可能会发生变化,因此需要在软路由上配置ddns服务。在软路由的终端里,编辑/etc/config/ddns
文件,示例如下:
config service 'noip_ipv6'
option lookup_host '(申请的域名)'
option use_ipv6 '1'
option update_url 'http://[USERNAME]:[PASSWORD]@dynupdate.no-ip.com/nic/update?hostname=[DOMAIN]&myip=[IP]'
option domain '(申请的域名)'
option ip_source 'interface'
option force_unit 'minutes'
option username '(noip的用户名)'
option password '(密码)'
option ip_interface 'pppoe-wan'
option enabled '1'
ddns的运行状况可以查看文件/var/log/ddns/noip_ipv6.log
。当IP信息更新成功时,可以看到类似于下面的信息:
215622 : DDNS Provider answered:
good 240e:0398:0412:13d3:7ae5:d616:xxxx:xxxx
215623 info : Update successful - IP '240e:0398:0412:13d3:7ae5:d616:xxxx:xxxx' send
需要注意的是:
- 国内访问noip比较慢,ddns发送地址更新消息可能会失败。ddns会定期重试,一般在几次重试后会更新成功
- 路由器重启后IPv6地址发生变化,ddns会自动更新地址。DNS record的更新需要一些时间,大概一个小时后整个数据访问流程会恢复正常。
以上是整个网络配置过程。我们在终端上使用域名和端口就可以访问到文件服务器了。由于域名解析后返回的是IPv6地址,因此需要任何要访问文件服务器的终端都要支持IPv6。
对于手机流量上网,目前电信和移动都是支持IPv6的,因此手机流量访问不会有问题。对于手机或者笔记本使用Wi-Fi路由器上网时,由于很多路由器默认是没有打开IPv6的,因此无法访问服务。这时需要打开路由器的IPv6功能。以我使用的TP-Link为例,在IPv6设置栏中,直接点击’开启‘,就可以。
对于笔记本,也需要在有线或者无线网卡设置中,勾选IPv6:
以上是路由和终端配置的整个过程,工作一直正常。而最近新遇到一个问题:当使用笔记本在家里访问某些网站时(此处略去网站名。。。),网页无法加载。经过调查后发现了原因:某网站会优先使用IPv6地址进行通信。由于我家里的网络是支持IPv6的,因此笔记本在欲访问某网站时得到了网站的IPv6地址。在使用此地址时,不知道为什么,就会导致无法和网站正常通信的问题。
由于我的这套方案需要使用IPv6才能访问自己的文件服务器,因此需要保留对IPv6的支持。那么解决方案就是当访问某网站时,让DNS返回无效的IPv6地址。这里需要用到软路由中的dnsmasq。编辑软路由中的文件/etc/dnsmasq.conf
, 增加下面的设置:
server=/abcabc.com/#
address=/abcabc.com/::
这里以abcabc.com
为例,设置后对它的DNS查询会返回无效的IPv6地址。
配置好后,在/etc/init.d
中, 使用./dnsmasq stop
和./dnsmasq start
重启服务。这时可以在笔记本里检查:
C:\Users\xiaop>ping -6 www.abcabc.com
Ping 请求找不到主机 www.abcabc.com。请检查该名称,然后重试。
说明现在已经不能解析到网站的IPv6地址了。接着再尝试:
C:\Users\xiaop>ping www.abcabc.com
正在 Ping www.abcabc.com [xxx.xxx.xxx.xxx] 具有 32 字节的数据:
IPv4地址的DNS请求正常。
注意:对于一个网站,往往具有多个域名来为其分流,所以需要查询网站的所有域名,逐一在dnsmasq.conf中添加上面的域名解析配置。