有了这样的需求,便着手搭建服务器了,最先的问题是:如何访问到私有服务器的?以往搭建服务器往往是使用aliyun,自然而然会提供公网IP地址,直接就能访问到。

一、 花生壳内网渗透尝试

在网上首先查到的是花生壳的内网渗透服务。经过与客服联系,终于知道了内网渗透的原理:添加端口映射后,访问域名则先会访问花生壳转发服务器(103.100.61.124),通过转发服务器代理访问内网对应端口的服务。所答复的数据都要经过花生壳进行转发,因此花生壳相当于一个反向代理,对于流量和带宽都有很大限制。

img

img

作为免费用户,能提供两个端口映射,每月1G的流量和1M的带宽。1M是什么概念?125kB/s,如果是导航页,或仅有文字的网页还能接受,但是带有图片的网站很难提供稳定的服务,更不用说NAS服务器了。

img

但内网渗透还是有一个好处的:公网IP不允许开启的80端口,可以使用内网渗透映射到一个导航页上,毕竟导航页仅仅提供一些链接,端口难以记忆的情况下方便的跳转到其他链接。

二、 公网IP+NAT+DDNS

通过http访问私有服务器都需要唯一主机定位地址,即Ipv4地址。由于Ipv4地址的稀缺性,通常来说,宽带公司不可能提供公网IP的。即使有了公网IP,在拨号上网的设备上也需要进行相应的设置使内网主机对应端口的服务对外可见。除此之外,申请的公网IP地址一般是动态的,同时也不好记忆,域名动态绑定就能很好解决问题。

1. 申请公网IP

最开始以为申请公网IP是一个很复杂的事情,还要编撰各种理由。但打了10000后,小哥只问了“为什么要转公网IP”,我说“家里要装监控”,对方没有再问“今天下午就帮您转公网”,很顺利全程不到5分钟。

实际上等到晚上,在路由器上看WAN IP还是内网IP:192.168.. ,才知道路由器并非拨号上网的,而是通过DHCP,前面还有一个“天翼”网关,所以不能从路由器看到公网IP。解决方式有两种:光猫改桥接,或光猫设置端口映射,我选择了前者。

拨打10000后,电信这边却拒绝了,“家庭用户光猫是不能改桥接的”,自己登陆192.168.1.1试图去手动改,由于光猫的型号不同,只有超级密码才能改,只能作罢。正巧家里电视机机顶盒坏了,请了维修小哥,小哥比较爽快,问“为什么要转桥接”,答“要在路由器上设置些东西”,便很快帮我转了。

2. 光猫+路由器NAT设置

路由器拨号上网之后,WAN IP已经是公网IP了,与ip138显示的相同。接下来仅仅需要简要设置一下端口映射,登陆路由器很方便就能设置:开了22, 9000-9019端口(分别提供远程连接和网络服务),其实端口号无所谓,之后可以通过域名url跳转。最好不要用80端口,可能被查封

img

img

3. 动态域名绑定DDNS

路由器本身确实提供DDNS服务,但是正确设置之后,通过ip138.com查询域名依然不能映射到该有的地址,连接状态也有时会处于未连接,可能这种DDNS服务本身就不靠谱。

img

4. 自动化脚本DDNS

因此不再依赖设备,直接写脚本定时修改域名解析,好在oray提供一个方便修改的网页:http://diy.oray.com

使用一个简便的python脚本实现了端口的自动更新,但恼火的是随着chrome的更新,Chromedriver的版本已经不再适用。感谢荐获取Chrome版本并下载匹配的chromedriver这篇博客,能自动化更新chromedriver,这里也不重复造轮子了)。

  • 自动下载chromedriver代码直接访问:driver.py
  • 自动DDNS脚本如下:
import time
import requests
import re
from selenium import webdriver
url = 'http://diy.oray.com'
interval = 2
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--headless')  # 增加无界面选项
driver = webdriver.Chrome(chrome_options=chrome_options)
driver.get(url)
time.sleep(interval)
# 注意更改域名和密码!
driver.find_element_by_xpath('//*[@id="login"]/div[3]/form/div[1]/div/input').send_keys('sunie.top')
driver.find_element_by_xpath('//*[@id="login"]/div[3]/form/div[2]/div/input').send_keys('XXX')
time.sleep(interval)
driver.find_element_by_xpath('//*[@id="login"]/div[3]/form/div[3]/div/button').click()
time.sleep(interval)
driver.find_element_by_xpath('//*[@id="nav"]/a[2]').click()
time.sleep(interval)
# 寻找类型为A的记录
i=2
index = i
while True:
    try:
        type = driver.find_element_by_xpath('//*[@id="app"]/div/div[3]/table/tbody/tr[{}]/td[2]'.format(i)).text.strip()
        print(i, type)
        if type == 'A':
            index = i
            break
        i += 1
    except:
        break
ip = driver.find_element_by_xpath('//*[@id="app"]/div/div[3]/table/tbody/tr[{}]/td[4]'.format(index)).text.strip()
ip_wan = re.findall(r'\d+.\d+.\d+.\d+', requests.get('http://txt.go.sohu.com/ip/soip').text)[0].strip()
print('花生壳映射ip: ' + ip)
print('本机外网ip: ' + ip_wan)
if ip == ip_wan:
    print('consistent!')
else:
    print('not consistent, trying to change the reflection!')
    # 删除映射
    driver.find_element_by_xpath('//*[@id="app"]/div/div[3]/table/tbody/tr[{}]/td[7]/a[2]'.format(index)).click()
    # 添加新映射
    driver.find_element_by_xpath('//*[@id="app"]/div/div[3]/table/tbody/tr[1]/td[4]/input').send_keys(ip_wan)
    time.sleep(interval)
    driver.find_element_by_xpath('//*[@id="app"]/div/div[3]/table/tbody/tr[1]/td[7]/a').click()

运行脚本,非常顺利地下载了chromedriver,进行了DDNS映射。

5. 定时运行ddns.py

试用了win10的任务计划程序,在每天0:00运行该脚本,每隔1小时运行一次。

img

直接在程序和脚本内输入powershell -windowstyle hidden -command 'python E:\Server\python_utils\ddns.py'可以隐藏小黑窗启动命令行

在linux中创建文件/Server/sh/ddns.py

#!/bin/bash
source /etc/profile
/root/anaconda3/bin/python /Server/python_utils/ddns_linux.py >> /Server/python_utils/ddns_linux.log 2>&1
ps -aux | grep chrome | awk '{print $2}' | xargs kill -9

启动crontab -e,添加*/20 * * * * bash /Server/sh/ddns.py即可

注意* */1 * * * 不是每小时执行一次,而是每分钟执行,因为在分(第一个*)上,没有指定具体的分钟,因此他就默认了每分钟执行一次

三、DDNS的另一种方案

实际上有的家用路由器,本身就支持ddns服务(大多数不便宜的路由器都支持),比如我使用的TL-WDR7661千兆版,登录路由器管理界面可找到DDNS服务。

img

使用TP-LINK可绑定域名以.tpddns.cn为后缀的网址。

img

然而这并非所期望的域名,遗憾的是,而在diy.oray.com,不支持域名设置显性或隐性url跳转到tpddns.cn结尾的域名