前言

我经常在本地一台闲置的服务器上,部署和测试一些分布式服务,但是因为网络问题,无形中增加了很多的学习成本。于是我将本地服务器上的所有 VM 或者 Docker 的代理都指向我的 macOS 主机,这样就避免了很多时候因网络导致的服务部署失败!

但是问题来了,例如我的 macOS 是通过共享办公的 Wi-Fi 连接网络,IP 地址是 DHCP 自动获取的,改为手动又容易有冲突,所以我就想通过 Consul 的服务注册来实现动态注册 Surge 的 HTTP Proxy 服务。

Surge Script

在 Surge 配置文件中增加如下设置:

[Script]
consul = type=event,event-name=network-changed,debug=1,script-path=network-changed.js

保存配置文件后,Surge Reload 后可以在 UI 中看到为如下设置:

Script Config Script Editor

Surge 可以通过 Script 来修改请求或者监听事件,然后发送请求,Surge 支持如下脚本触发模式:

  • HTTP Request
  • HTTP Response
  • Rule
  • Event
  • DNS
  • Cron
  • Generic

我这里用的是 Event 模式,Surge 暴露了两种事件类型:

  • network-changed
  • notification

当网络发生变化时,会触发 network-changed 事件,然后调用我定义的 Script。

$httpClient.put({
	url: "http://consul.service.betterde.consul:8500/v1/agent/service/register",
	body: {
        "id": "surge-http",
        "name": "surge",
        "port": 6152,
        "address": $network.v4.primaryAddress,
        "check": {
            "Name": "Surge HTTP proxy service check",
            "TCP": $network.v4.primaryAddress + ":6152",
            "Interval": "60s"
        }
    }
}, function(error, response, data) {
    if (error) {
        $done(error);
    } else {
        $done({response});
    }
});

在脚本中 Surge 暴露了一些全局变量,要获取内网 IP 可以通过 $network.v4.primaryAddress 来获取,然后通过 Surge 内置的 $httpClient 来实现向 Consul 注册服务。

Surge Proxy service

服务器配置

sudo mkdir -p /etc/systemd/resolved.conf.d
sudo vim /etc/systemd/resolved.conf.d/consul.conf

将下面配置写入 /etc/systemd/resolved.conf.d/consul.conf 配置文件中:

[Resolve]
DNS=127.0.0.1:8600
DNSSEC=false
Domains=~consul

注意:因为我的 Consul 是安装在虚拟机上的,所以这里的地址就是本地的 Loopback IP。

然后重启 DNS 解析服务:

sudo systemctl restart systemd-resolved

验证结果

dig surge.service.betterde.consul

; <<>> DiG 9.18.1-1ubuntu1.3-Ubuntu <<>> surge.service.betterde.consul
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 18152
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;surge.service.betterde.consul.	IN	A

;; ANSWER SECTION:
surge.service.betterde.consul. 0 IN	A	10.192.6.137

;; Query time: 0 msec
;; SERVER: 127.0.0.53#53(127.0.0.53) (UDP)
;; WHEN: Thu Apr 13 13:40:02 CST 2023
;; MSG SIZE  rcvd: 74

可以看到,解析出来的 IP 正是我 macOS 的当前 IP,这样就可以在 Docker 或者环境变量中使用 surge.service.betterde.consul 这个内部域名作为代理服务器地址了,而不是 macOS 的动态 IP。

I hope this is helpful, Happy hacking…