我复杂的网络环境中,proxy是个很有用的工具,我们可以通过proxy代理帮我们完成网络流量的转发。
这个proxy得先能接收请求,所以这里先启动一个tcp的监听,获取请求
func (s *Server) Start() {
var err error
s.listener,err = net.Listen("tcp",s.addr)
if err != nil {
glog.Fatal(err)
}
glog.Infof("proxy listen in %s,waiting for connection...\n",s.addr)
for {
conn,err := s.listener.Accept()
if err != nil {
glog.Error(err)
continue
}
go newConn(s,conn).serve()
}
}
func (c *conn) serve() {
defer c.netConn.Close()
rawHttpRequestHeader,remote,isHttps,err := c.getTunnelInfo()
if err != nil {
glog.Error(err)
return
}
glog.Info("connecting to " + remote)
remoteConn,err := net.Dial("tcp",remote)
if err != nil {
glog.Error(err)
return
}
if isHttps {
glog.V(10).Infof("get https req remote %s \n",remote)
// if https,should sent 200 to client
_,err = c.netConn.Write([]byte("HTTP/1.1 200 Connection established\r\n\r\n"))
if err != nil {
glog.Error(err)
return
}
} else {
// if not https,should sent the request header to remote
_,err = rawHttpRequestHeader.WriteTo(remoteConn)
if err != nil {
glog.Error(err)
return
}
}
// build bidirectional-streams
glog.Info("begin tunnel",c.netConn.RemoteAddr(),"<->",remote)
c.tunnel(remoteConn)
glog.Info("stop tunnel",remote)
}
getTunnelInfo是获取连接信息的,譬如访问host、port、协议和请求头之类的东西。
然后就可以建立远程连接,通过net.Dial(“tcp”,remote)建立。
最后就是简单复制流量c.tunnel(remoteConn),具体代码如下
_,err := io.Copy(c.netConn,remoteConn)
这样就可以通过它转发流量
下面是例子
启动服务
./goproxy --addr :9999 --log_dir=/tmp/goproxy --v=10
到另外的机器上面执行
http:
curl --proxy 10.39.0.45:9999 http://10.39.0.45:9090
https:
curl -k --proxy 10.39.0.45:9999 https://10.0.0.43:443
原文链接:https://www.f2er.com/go/187530.html