Skip to content

outbound 请求拦截原理

Mingliang Tan edited this page Feb 20, 2019 · 2 revisions

回放的时候,outbound rpc 的拦截不仅仅是需要录制下来,还要在没有集成环境的情况下真实地给一个响应。

我们当然可以拦截所有的 syscall 虚拟一个 tcp 链接出来。但是这样的实现代价太高了。

直接的做法是真实地起了一个 tcp 服务器做为通用的 outbound server。然后所有的 outbound rpc 在做 connect 系统调用的时候把目标的 ip:port 给修改了。业务以为请求的是 a,实际 connect 到的是 b。达到 mock server 伪造的目的。

if envarg.IsReplaying() {
    countlog.Debug("event!gw4libc.redirect_connect_target",
        "origAddr", origAddr,
        "redirectTo", envarg.OutboundAddr())
    sockaddr_in_sin_addr_set(remoteAddr, ch.Ip2int(envarg.OutboundAddr().IP))
    sockaddr_in_sin_port_set(remoteAddr, ch.Htons(uint16(envarg.OutboundAddr().Port)))
}

本来 libc 拦截下来,在 Go 的代码里改一下 addr 对象的内容就可以。

因为 Go 对于 struct 里小写开头的 field 无法直接读写。所以,实际的实现是通过反射知道 struct field offset。然后通过 unsafe pointer 用指针运算绕过 Go 的可见性检查直接修改的。

这些 Go 和 C 打交道的小 trick 都封装到了ch(c helper 的意思)这个包里面。

Clone this wiki locally