DDNS服务被屏蔽后的中转方案
声明:本文禁止转载!
家里路由器里自带的花生壳DDNS非常不稳定,用个一两天就失效,非得重启路由器,令人无法忍受(我都上传身份证了啊!)。是花生壳的问题还是路由器的问题,不得而知。后来在国外dynu.com申请了一个域名,通过家里的树莓派运行ddclient自动更新IP,稳定用了好久。然而某一天开始,从家里再也连不上dynu了,原因你懂的。国内的还是不好用,于是开始琢磨曲线拯救方案。
中转API调用方案
幸运的是,我还有一台VPS可以连接,而从VPS上访问dynu是没问题的,于是就想到通过VPS间接更新DDNS。现学现用,人生第一次使用python写了个脚本(我容易吗我!)部署在VPS上。大致的工作流程是这样的:
- VPS上的Python脚本启动HTTP端口监听
- 家里的树莓派通过Crontab定时运行一条命令(就一个wget),访问VPS上的HTTP服务。访问的URL什么参数也不带,也不需要知道当前IP地址。
- VPS收到树莓派的HTTP请求,并根据HTTP协议从请求报文中解析获得访问者的IP地址(也就是家的IP)
- 脚本调用dynu的api,把IP发送给dynu更新。继续监听。
- 完成。
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,看上去不错,不过我懒得再折腾,等目前的方案哪天不行了再说吧。