DDNS服务被屏蔽后的中转方案

2019-06-13  本文已影响0人  重案组知乎

声明:本文禁止转载!

家里路由器里自带的花生壳DDNS非常不稳定,用个一两天就失效,非得重启路由器,令人无法忍受(我都上传身份证了啊!)。是花生壳的问题还是路由器的问题,不得而知。后来在国外dynu.com申请了一个域名,通过家里的树莓派运行ddclient自动更新IP,稳定用了好久。然而某一天开始,从家里再也连不上dynu了,原因你懂的。国内的还是不好用,于是开始琢磨曲线拯救方案。

中转API调用方案


幸运的是,我还有一台VPS可以连接,而从VPS上访问dynu是没问题的,于是就想到通过VPS间接更新DDNS。现学现用,人生第一次使用python写了个脚本(我容易吗我!)部署在VPS上。大致的工作流程是这样的:

  1. VPS上的Python脚本启动HTTP端口监听
  2. 家里的树莓派通过Crontab定时运行一条命令(就一个wget),访问VPS上的HTTP服务。访问的URL什么参数也不带,也不需要知道当前IP地址。
  3. VPS收到树莓派的HTTP请求,并根据HTTP协议从请求报文中解析获得访问者的IP地址(也就是家的IP)
  4. 脚本调用dynu的api,把IP发送给dynu更新。继续监听。
  5. 完成。

Python脚本如下(VPS系统比较老,Python版本是2.6.6):

from BaseHTTPServer import BaseHTTPRequestHandler
import httplib

class DDNSHandler(BaseHTTPRequestHandler):

    def do_GET(self):

        if self.path == '/dnproxy':
            self.updateDDNS(self.client_address[0])
            
            self.send_response(200)
            self.send_header('Content-type', 'text/html')
            self.send_header('connection', 'close')
            self.end_headers()
            self.wfile.write("<HTML>OK.</HTML>")

        elif self.path == '/test':
            print("Test...")
            self.send_response(200)
            self.send_header('Content-type', 'text/html')
            self.send_header('connection', 'close')
            self.end_headers()
            self.wfile.write("<HTML>OK.</HTML>")  
        
        elif self.path == '/quit':
            print("Quit...")
            global KEEP_RUNNING
            KEEP_RUNNING = False
        
        else:
            print("Request wrong url:", self.path)
            self.send_error(404, "")


    def updateDDNS(self, ipv4):
        
        global SiteInfo
        
        SiteInfo["myip"] = ipv4
        
        conn = httplib.HTTPConnection("api.dynu.com")
        url = "https://api.dynu.com/nice/update?username={username}&password={password}&hostname={hostname}&myip={myip}&myipv6=no"
        url = url.format(**SiteInfo)
        print(url)
        conn.request(method="GET",url=url) 
        
        response = conn.getresponse()
        res= response.read()
        print(res)
 
# 修改这里的dynu账号信息   
SiteInfo = {"username": "YOUR_USER_NAME",
        "password": "YOUR_PASSWORD",
        "hostname": "YOUR_DOMAIN_NAME"}    

KEEP_RUNNING = True

def keep_running():
    return KEEP_RUNNING

if __name__ == '__main__':
    # Start a simple server, and loop forever
    from BaseHTTPServer import HTTPServer
    server = HTTPServer(('0.0.0.0', 44444), DDNSHandler)
    print("Starting server, use <Ctrl-C> to stop")
    #server.serve_forever()    
    while KEEP_RUNNING:
        server.handle_request()
Exit code: 0

这个程序运行后监听44444端口。从任何地方只要访问"http://[vps_ip_address]:44444/dnproxy/",就会把当前所在地的IP地址更新到你的域名上。因为使用HTTP GET而不是POST,所以直接用浏览器就可以调试,很方便。另外还有个/test路径用于测试,/quit路径用于退出服务程序。另外注意,这个程序简单到没有做任何安全防范,任何人知道地址都能替你更新ddns,所以必须小心自用,不要泄露。另外,也没有考虑访问线路中是否有其他网络设备会篡改HTTP请求头,从而无法获得正确IP地址的问题。

本来技术上来说也可以在VPS上部署一个HTTP代理服务器,让树莓派通过代理调用dynu的API,这样都不用开发服务器脚本了,但考虑到代理服务容易被识别拦截,搞不好会殃及VPS,而且树莓派也要写脚本调用外部网站接口来获取当前IP,有点麻烦,所以最终采用看上去完全无害、没有任何可疑关键字(除了我的VPS地址)的单纯HTTP GET指令来隐式传递IP地址信息。

这个方案又用了好一阵子,直到有一天,VPS也连不上了。。。于是一番搜索,又有了下面的更简单的方案。

DDNS代理更新服务商方案


其实我一开始很纠结该不该说这个方案,一旦用的人多了,可能很快就会废掉,不过转念一想,我能有这么大的影响力吗?想多了吧!但是如果有朋友看了文章觉得有用,请保护有限资源,自己用就行了,

不要转载!不要转载!不要转载!

dnsomatic,相当于一个DDNS的聚集门户,可以通过它间接连接多个DDNS服务商,实现一处更新,处处更新的效果,他支持的DDNS服务商非常多,请自行去官方主页查看。

使用方法很简单,注册一个账户,并添加你实际使用的DDNS服务商的账号信息(可以添加多个,我只有一个),然后用客户端定时调用它的接口更新IP就行了。我仍然使用ddclient作为客户端,但它也支持其他的,请自行去官方主页查看。

ddclient的配置文件/etc/ddclient.conf配置如下(需要自行替换其中的账号密码):

# Configuration file for ddclient generated by debconf
#
# /etc/ddclient.conf

ssl=yes
use=web, web=myip.dnsomatic.com
server=updates.dnsomatic.com,      \
protocol=dyndns2,                  \
login=YOUR_DNS_O_MATIC_ACCOUNT,          \
password=YOUR_DNS_O_MATIC_PASSWORD        \
all.dnsomatic.com

可以使用ddclient的调试模式,打印详细的更新过程确认配置运行是否正常:

sudo ddclient -daemon=0 -debug -verbose -noquiet

如果一切顺利的话,就可以在这里看到更新记录了:


更新记录

最后别忘了把ddclient配置成系统服务。

其他


很多人推荐用阿里DDNS,看上去不错,不过我懒得再折腾,等目前的方案哪天不行了再说吧。

上一篇 下一篇

猜你喜欢

热点阅读