USG快速实现免费花生壳DDNS自动上报

在USG快速实现免费花生壳DDNS自动上报

很早以前坛子里有过一篇关于EdgeMAX Router系列产品配置花生壳DDNS的短文。「见:3322及花生壳的ddns更新方法」在Unifi体系下控制器升级到新版本之后没有了SSL=NO的选项*「可能米蒂研发产品人觉得安全比能用更重要吧」*,而且没有了额外参数的导入选项,以至于类似花生壳、2233这样的原版的变体衍生服务无法使用,有很多童鞋询问过USG系列如何实现,一直没什么好的方法解决。
其实五一节的时候,我就试着弄过一回,发现可以实现但是会被系统同步配置的时候恢复,当时就记录了一下,没追究原因,这次十一放假闲出来半天,想就搞起!

一、阅读须知:)

先说前提条件,不符合的直接出门右拐就好:P
本文仅适合下面的最简环境条件「未有计划扩展到其他应用环境,有能力的可以自己扩展研究」

  1. 单个出口链路「文中样例是PPPoE拨号,中国电信」
  2. 单个DDNS「文中样例是免费花生壳账号,(按说2233是一样的,童鞋们可以自己测试)」
  3. DDNS更新由USG的自动拨号脚本启动发起,缺省有效期28天,存在非显式参数可以调整,个人觉得没必要调整,因为USG每次WAN口获得新IP的时候会自动发起更新DDNS记录的逻辑;有强迫症的可以自己去查这个非显式的参数,然后再寻找方法更改,本文不讨论这个问题。「很大可能涉及config.gateway.json的修改,跟本文是两个探索方向,配置模式和方法完全不同,因此不并在一起讨论了」

二、USG实现免费花生壳的障碍

  1. SSL=NO选项:u7121:
  2. Option参数输入项:u7121:
  3. 修改的配置会被同步或重启的附加逻辑覆盖
    障碍1和障碍2可以参考ER系列的来更改,但是障碍3是USG系列独有的问题,所以需要额外对待才能解决。

三、解决DDNS障碍的原理说明「不想看的直接跳过直奔操作章节即可:P」

3.1 发现重写覆盖机制

由于USG的DDNS配置是直接由Unifi控制器下发的,格式是一个JSON文件,但是从config.gateway.json文件中未找到合适的参数修改的地方,显式的几个参数都不涉及SSL和Option参数,尝试几次修改后无果;
换了一个方向就是想像ER那样修改ddclient-pppoe0.conf文件就会招致系统同步和USG重启时的自动覆盖,仅能一次有效……
从ddclient-pppoe0.conf的文件内容可以发现:

root@ubnt:~# cat /etc/ddclient/ddclient_pppoe0.conf
#
# autogenerated by vyatta-dynamic-dns.pl on Mon May 18 10:02:07 CST 2020
#
daemon=1m
syslog=yes
ssl=yes
pid=/var/run/ddclient/ddclient_pppoe0.pid
cache=/var/cache/ddclient/ddclient_pppoe0.cache
use=if, if=pppoe0


# Service : dyndns
server=ddns.oray.com, protocol=dyndns2 max-interval=28d login=12345678 password='12345678' 12345678.oicp.■■■

root@ubnt:~# 

这个文件自己提示了autogenerated by vyatta-dynamic-dns.pl on Mon May 18 10:02:07 CST 2020是由vyatta-dynamic-dns.pl脚本自动生成的,而且生成时间正好是五一那段时间我测试的时候,因此可以判断这个脚本在重启或其他业务逻辑的触发下会动态编译出文件且自动重写整个DDNS的登陆配置文本,导致我们的修改被覆盖。

3.2 修改方法

考虑修改方法,根据坛子里其他帖子的提示,很快找到了vyatta-dynamic-dns.pl这个脚本,试了一下使用vi修改是可以保存的,那么剩下就是找到修改的地方了,很多章节的代码段存在判断和条件,没心思和时间慢慢琢磨,就直接找到了生成配置文本的根位置,就是自动生成DDNS拨号文件的脚本部分。大致这样:

sub dynamicdns_get_constants {
    my $output;

    my $date = `date`;
    chomp $date;
    $output  = "#\n# autogenerated by vyatta-dynamic-dns.pl on $date\n#\n";
    $output .= "daemon=1m\n";
    $output .= "syslog=yes\n";
    $output .= "ssl=yes\n";
    $output .= "pid=$ddclient_run_dir/ddclient_$interface.pid\n";
    $output .= "cache=$ddclient_cache_dir/ddclient_$interface.cache\n";
    return $output;
}

尝试了一下修改这部分就可以让最终输出的ddclient-pppoe0.conf按照我们的想法改变。而且重启和强制同步均没有影响,毕竟是每次都按照这个脚本覆盖重写的,当然没问题。

3.3 小心坑点「危险:warning:警告」

不过这个文件的改动要非常小心,我在尝试的时候改错几个地方,导致USG同步失败且无限循环同步,这个比较危险,童鞋们想尝试额外改动的话请慎之又慎。

四、快速操作指南「实操实验记录」

4.1 前期准备参数&条件

  • DDNS服务器域名 :ddns.oray.com
  • DDNS用户账号:abcdefgh
  • DDNS用户密码:12345678
  • DDNS域名:abcdefgh.oicp.■■■
  • SSL:yes OR no 「免费花生壳是no,收费的大部分是yes」
  • Script:/ph/update 「免费花生壳是这个,其他的请自己询问服务商即可」
  • 确认USG接到公网的逻辑WAN接口「PPPoE拨号的是pppoe0这样的,如果是DCHP或固定IP的情况下,WAN1口就是eth0,WAN2是eth2」

4.2 Unifi控制器上的操作

这部分操作是让系统自动生成动态DNS的脚本

  1. 在AC上的UI界面进入SETTINGS/Services/DYNAMIC DNS
  2. 点击+CREATE NEW DYNAMIC DNS
  • Interface:选取接外网的正确接口即可「这里PPPoE拨号的应该也是选择用的哪个物理端口」
  • Services:花生壳的话请选dyndns「2233应该也是这个」
  • Hostname:填自己的花生壳域名,就是你打算外网访问自己用的那个域名
  • Username:花生壳账号
  • password:对应上面账号的密码
  • Server:更新域名用的服务器「不知道的咨询花生壳那边,有好几个服务器,看你的账号归哪个服务器管理」

4.3 验证修改能不能执行「非必要,但是建议照做」

其实这4.3章节是额外的,你能确信自己操作没问题的可以越过这个章节,直接从4.4章节开始的。但是真遇到问题了,还是要退回来在这里寻找源头。这章节里还有一些调试的命令也对分析问题有帮助的

SSH登陆到USG

用站点密码SSH到USG上「不会的请度娘,或者看官方支持文档:网络简介 - 如何使用 SSH 建立连接
此时可以用show dns dynamic status命令来显示当前的DDNS状态:
eg.

ubnt@ubnt:~$ show dns dynamic status 
interface    : pppoe0
ip address   : 
host-name    : abcdefgh.oicp.■■■
last update  : Thu Jan  1 08:00:00 1970
update-status: noconnect

可以看到最后两行里显示的是从未更新成功过,状态也是没连接的。

修改DDNS脚本

开启权限

在命令行下输入sudo -i 开启「提升」编辑权限:
eg.

ubnt@ubnt:~$ sudo -i
root@ubnt:~# 
找到目标conf文件

先找到conf文件的文件名具体文件名可以用ls /etc/ddclient来查询,如果没有代表前面一步4.2章节的操作还没做对;
eg.

root@ubnt:~# ls /etc/ddclient 
ddclient_pppoe0.conf
root@ubnt:~# 
显示当前conf文件

在命令行下输入 cat /etc/ddclient/ddclient-pppoe0.conf 当然你的WAN口是DHCP的话就把ddclient-pppoe0.conf换成你找到的那个ddclient-eth0.conf这样的。
eg.

root@ubnt:~# cat /etc/ddclient/ddclient_pppoe0.conf
#
# autogenerated by vyatta-dynamic-dns.pl on Mon May 18 10:02:07 CST 2020
#
daemon=1m
syslog=yes
ssl=yes
pid=/var/run/ddclient/ddclient_pppoe0.pid
cache=/var/cache/ddclient/ddclient_pppoe0.cache
use=if, if=pppoe0


# Service : dyndns
server=ddns.oray.com, protocol=dyndns2 max-interval=28d login=abcdefgh password='12345678' abcdefgh.oicp.■■■

root@ubnt:~# 
编辑conf文件

~注意:warning::在编辑文档操作的时候,把键盘改到小写E文模式,千万别大写中文模式来坑自己哦,这个应该说三遍的!!!~
在命令行下输入 vi /etc/ddclient/ddclient-pppoe0.conf 当然你的WAN口是DHCP的话就把ddclient-pppoe0.conf换成你找到的那个ddclient-eth0.conf这样的。
vi是一个文件编辑器,具体使用说明可以参考这个:linux-vim
由于我们仅仅是简单的使用编辑,所以不用全面学会,简单几招就够用了;
i命令进入编辑状态
Esc退出编辑进入命令行
命令状态下
:w保存
:q退出
那么我们在上述那个conf文件里要改的就是如下几个

  • 付费用户ssl=yes不改就行,免费用户改成ssl=no
  • 在ssl上面加一行script=/ph/update
    记得保存、退出。conf那段变成如下:
    「就改那一行字,再增加一行字,其它一个字符都不要动,手残党一定特别注意,觉得改错了就直接:q!退出」
    eg.
daemon=1m
syslog=yes
script=/ph/update
ssl=no
pid=/var/run/ddclient/ddclient_pppoe0.pid
cache=/var/cache/ddclient/ddclient_pppoe0.cache
use=if, if=pppoe0

触发DDNS申请

在SSH命令行下输入 sudo ddclient -file /etc/ddclient/ddclient_pppoe0.conf -daemon=0 -debug -verbose -noquiet -force
这样可以强制执行触发DDNS,再用show dns dynamic status来看结果就好:

root@ubnt:~# show dns dynamic status 
interface    : pppoe0
ip address   : 202.202.202.202
host-name    : abcdefgh.oicp.■■■
last update  : Sun Jun 28 18:00:44 2020
update-status: good

可以看到最后两行里显示了更新成功的时间已经是今天的18点了,状态也是good了。「这个时候可以在控制器的UI界面点击左侧主菜单的:bulb:INSIGHTS,进入屏幕后左上角选择 Dynamic DNS 菜单就可以看到状态效果的显示了。」
以上4.3章节的内容就是我在五一节阶段所做的全部,这样的修改会被系统覆盖的,但是能证明你的所有参数的有效性,如果这部分都不能实现就没必要搞下去了。

4.4 终极修改pl脚本

「4.3章节里有的内容我就不重复说了,请童鞋们自己参照一下」

一样的前期工作

  1. 同样SSH到USG
  2. Sudo提权

编辑vyatta-dynamic-dns.pl文件

命令行输入 vi /opt/vyatta/sbin/vyatta-dynamic-dns.pl
这个文件有290+行,请找到我们要改的这段:

sub dynamicdns_get_constants {
    my $output;

    my $date = `date`;
    chomp $date;
    $output  = "#\n# autogenerated by vyatta-dynamic-dns.pl on $date\n#\n";
    $output .= "daemon=1m\n";
    $output .= "syslog=yes\n";
    $output .= "ssl=yes\n";
    $output .= "pid=$ddclient_run_dir/ddclient_$interface.pid\n";
    $output .= "cache=$ddclient_cache_dir/ddclient_$interface.cache\n";
    return $output;
}

修改的地方就2个:

  1. $output .= "ssl=yes\n";改成$output .= "ssl=no\n";
  2. 在ssl那行的上方增加一行$output .= "script=/ph/update\n";
    注意大小写,注意空格::warning: ~全小写E文,别坑自己!~
    改完之后应该是这样子:
sub dynamicdns_get_constants {
    my $output;

    my $date = `date`;
    chomp $date;
    $output  = "#\n# autogenerated by vyatta-dynamic-dns.pl on $date\n#\n";
    $output .= "daemon=1m\n";
    $output .= "syslog=yes\n";
    $output .= "script=/ph/update\n";
    $output .= "ssl=no\n";
    $output .= "pid=$ddclient_run_dir/ddclient_$interface.pid\n";
    $output .= "cache=$ddclient_cache_dir/ddclient_$interface.cache\n";
    return $output;
}

注意每行后面一定会跟一个“/n”换行符,这样就行了。记得保存后退出。再重启USG即可。

五、检验效果

在控制器的UI界面点击左侧边栏主菜单的:bulb:INSIGHTS,进入转进的屏幕后左上角选择 Dynamic DNS 菜单就可以看到状态效果的显示了。

六、副作用警告:warning:

现在可以推测出来的副作用如下:

  • 由于修改了原始的DDNS脚本,可能在配置其他DDNS时受到本帖里修改的影响而无法使用;
  • 由于修改的是dyndns协议模式,基本上这个协议的都会因为修改而改变,因此原始的dyndns协议都跟着改了,如果跟修改的参数不同的就无法用了;

学习了,学习了 :heart_eyes: :heart_eyes: :heart_eyes:

啊, Perl脚本啊, 就靠这个吃饭的. 但是我还是看不懂这个脚本是干嘛的.

我也懒得去看,review别人代码是最惨痛的工作之一…… :grimacing:素直接改就好,别问为啥,我也不知道为啥 :crazy_face:

官方支持下多好,反正已经内置了那么多~唉,国内支持还是不行。