还个愿
公司提供云服务器,但是云服务器处于内网,通过 NAT 转发将外网请求转发至处于内网的云服务器上。测试设备全部位于外网。部署 ATX-server 成功后,设备列表可以获取到设备信息,点击 use 后,操作页面手机画面空白,任何操作都没有。
通过抓包和观察,设备列表获取到的设备信息,IP 为转发服务器的 IP,而不是设备在外网的 IP。
atx-server 从心跳拿到设备 IP 的代码实现如下:
https://github.com/codeskyblue/realip/blob/master/realip.go
// FromRequest return real request IP
func FromRequest(r *http.Request) string {
for _, h := range []string{"X-Forwarded-For", "X-Real-IP"} {
for _, ip := range strings.Split(r.Header.Get(h), ", ") {
if net.ParseIP(ip) != nil {
return ip
}
}
}
remoteIp := r.RemoteAddr
if strings.ContainsRune(r.RemoteAddr, ':') {
remoteIp, _, _ = net.SplitHostPort(r.RemoteAddr)
}
return remoteIp
}
以上三种方法,请求头中 X-Forwarded-For ,X-Real-IP 的数值为空,r.RemoteAddr 就是转发服务器 IP,但是提供了两个可能的解决的方法,都是在 atx-agent 的心跳请求上修改,一个是人为增加请求头 X-Forwarded-For 或者 X-Real-IP 为设备 IP,一个是请求中将 IP 作为参数带过来,atx-server 接收 ip 后,将 ip 替代原本获取 ip 的方法。
我选择的是第二种方法。(orz go 速成选手)
// https://github.com/codeskyblue/heartbeat/blob/master/heartbeat.go 210-213
resp, err := httpclient.PostForm(serverAddr, url.Values{ // TODO: http timeout
"timestamp": {serverTimeKey},
"identifier": {c.Identifier},
"messageMAC": {hashIdentifier(serverTimeKey, c.Identifier, c.Secret)}})
修改成
resp, err := httpclient.PostForm(serverAddr, url.Values{ // TODO: http timeout
"timestamp": {serverTimeKey},
"identifier": {c.Identifier},
"messageMAC": {hashIdentifier(serverTimeKey, c.Identifier, c.Secret)},
"ip":{mustGetOoutboundIP().String()}},)
前提要把作者写的获取 IP 的代码段拷贝进 heartbeat.go (比较怂,不敢直接引用,直接拷贝代码)
// Get preferred outbound ip of this machine
func getOutboundIP() (ip net.IP, err error) {
conn, err := net.Dial("udp", "8.8.8.8:80")
if err != nil {
return
}
defer conn.Close()
localAddr := conn.LocalAddr().(*net.UDPAddr)
return localAddr.IP, nil
}
func mustGetOoutboundIP() net.IP {
ip, err := getOutboundIP()
if err != nil {
return net.ParseIP("127.0.0.1")
// panic(err)
}
return ip
}
\\https://github.com/openatx/atx-server/blob/master/httpserver.go 452
host := realip.FromRequest(r)
修改成
host := r.Form.Get("ip")
## https://github.com/openatx/uiautomator2/blob/master/uiautomator2/__main__.py 243
## 将bin_path 赋值重新编译的atx-agent本地地址即可
self.push(bin_path, agentpath, 0o755)