ATX [已解决] 公司内网部署 atx-server,获取不到设备真实 IP

剪烛 · 2019年01月30日 · 1581 次阅读

还个愿

问题描述

公司提供云服务器,但是云服务器处于内网,通过 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 速成选手)

1.clone atx-agent 按照指引在本地编译成功
2.找到发送 heartbeat 的代码,修改以下片段
//  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
}
3.修改 atx-server 接收心跳代码,替换 ip 获取方式
\\https://github.com/openatx/atx-server/blob/master/httpserver.go  452
host := realip.FromRequest(r)

修改成

host := r.Form.Get("ip")
4. 按照指引重新编译 atx-agent ,并且替换 uiautomator2 init 中关于 atx-agent 的地址(但是貌似看了代码,似乎如果 atx-agent 正在运行,并且版本号相同,就不会替换)
## https://github.com/openatx/uiautomator2/blob/master/uiautomator2/__main__.py 243
## 将bin_path 赋值重新编译的atx-agent本地地址即可
self.push(bin_path, agentpath, 0o755) 

以上方法应该适用于 atx-server 部署在云服务器,但是测试设备和使用者 处于同一个局域网下的情况。

orz 多谢被我不停骚扰的各位大佬。

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
暂无回复。
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册