RouterOS脚本之更优雅的使用(动态)域名作为WireGuard Peer地址

发布日期:分类:Linux & homelab RouterOS脚本之更优雅的使用(动态)域名作为WireGuard Peer地址有 1 条评论

Update:较新的RouterOS v7.11已经带有了此功能(未测试),或许无需再使用该脚本

摘要:这篇文章给出了一种对于Router OS的更“优雅“的WireGuard Peer Endpoint(动态)域名自动刷新脚本,提出了一种在配置项的COMMENT中填写变量(比如域名)的方法,而不是hardcode在脚本中。这种思想也可用于其他对于RouterOS功能扩展的脚本。

背景:这个需求来源于Router OS的一个bug或者毛病,即当配置WireGuard Peer的连接地址(Endpoint)时,你虽然可以使用域名,但其仅会在启动时被解析,之后如果域名的IP发生变化,是不回重新解析的。这就导致如果你使用DDNS域名作为Endpoint,那在其IP变化后连接就会丢失,不会自动恢复,直到你重启接口或者机器。

解决上述问题的方式就是编写一个Router OS的脚本来解析域名,并将其IP更新到WireGuard Peer的Endpoint项中,然后将这个脚本添加在Schedule中,定时自动执行。由于Endpoint项会被脚本填写的IP覆盖,因此要在别的地方记录其域名。这个脚本目前网络上流传的版本如下:

# 网络上流传的版本,灵活性较差
:local wgInterface
:local wgPeerDns

:set wgInterface "wireguard1"
:set wgPeerDns "xxxxxxx.xxx-ddns.net"

:if ([interface wireguard peers get number=[find interface="$wgInterface"] value-name=endpoint-address] != [resolve $wgPeerDns]) do={
  interface wireguard peers set number=[find interface="$wgInterface"] endpoint-address=[/resolve $wgPeerDns]
}

可以看出其WireGuard的接口和域名都hardcode(写死)在了脚本中,并且其默认一个接口只有一个Peer,无法适用于一个接口有多个Peer的情况。虽然我们很容易就能对其进行修改让其支持,但仍是繁琐的,比如要根据pubkey或设置特定的Comment用于区分不同Peer,并在脚本中对照配置项进行填写,带来了维护上的繁琐。

方法:既然这类脚本的目的是对Router OS本身的功能进行扩展,那么对于配置时最自然的方式,就是可以在配置项原有的界面中一并填写相关的变量(比如此处的域名),虽然Router OS中我们不能给配置项再添加一个字段,但我们其实可以充分利用Comment字段来存放我们的变量,有点像加在linux命令前的环境变量。并且Comment本身就和每个配置项直接关联,不需要我们再去维护其对应关系。

例如,我们就可以在Comment里写上DOMAIN_ENDPOINT=xxxxxxx.xxx-ddns.net来表示域名,像下面这样:

相应的这种更优雅一些的脚本如下:

/interface/wireguard/peers

:local CommentPrefix "DOMAIN_ENDPOINT="

:foreach i in=[find where comment~"^$CommentPrefix.*\$"] do={
    :local comment [get number=$i comment]
    :local ip [:resolve [:pick $comment [:len $CommentPrefix] [:len $comment]]]
    
    :if ([get number=$i endpoint-address] != $ip) do={
        set number=$i endpoint-address=$ip
    }
}

由于所有配置相关的信息都在Comment中填写了,哪怕之后还需要修改Peer的地址或者添加新的Peer和接口,也不需要对脚本进行任何更新。同时,如果Comment中没有“DOMAIN_ENDPOINT=”这样的字符串,脚本不回对其做任何操作;比起直接将整个Comment区域作为特定的变量值,这样不会有任何副作用,并且对于维护时该变量的含义是“自解释”的。

结论:这是对于WireGuard Peer动态域名的一个实用的脚本,但对于这种“通过Comment区的特定语法来配合一个通用的脚本来对Router OS的功能进行扩展”的思想,这只是一个简单的例子。实际上,还可以实现如:兼容与普通Comment一起使用,可以填写多个变量等,就“交给读者作为练习”了。

作者:WuSiYu

学生,Web开发者,智能硬件&IOT爱好者

1条评论

发表评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注