Home / 开发 / golang开发机场v2ray节点ws协议前置代理,实现直连v2ray永不被封锁
最近在给顶部广告的机场做开发个小工具,顶部广告机场需求是不用国内服务器和不被封锁。
想到了aws,换ip免费。
ws协议做服务器前置。
老板也答应可以分享思路和放出部分代码,在这里做下分享。
思路流程图:
同时给老板写了个类似探针的页面,可以直面的查看各个节点的在线状态
websocket 流量代理,golang代码,我想应该可以直接对接v2ray内核这样效率会更高。
// 判断是否是websocket请求
if strings.ToLower(r.Request.Header.Get("Connection")) != "upgrade" ||
strings.ToLower(r.Request.Header.Get("Upgrade")) != "websocket" {
r.Response.Write([]byte(`Must be a websocket request`))
return
}
defer r.Body.Close()
// 劫持连接
// conn, _, err := r.Response.Writer.Hijack()
conn, _, err := r.Response.Hijack()
if err != nil {
return
}
defer conn.Close()
// 克隆请求,设置目标地址路径 ws://192.168.0.1:80/get
websocketUrl, _ := url.Parse(websocket.WebsocketD.Url)
req := r.Request.Clone(r.Context())
req.URL.Path, req.URL.RawPath, req.RequestURI = websocketUrl.Path, websocketUrl.Path, websocketUrl.Path
req.Host = websocketUrl.Host
// 握手之前设置请求头
for _, vv := range websocket.WebsocketHeaderD {
req.Header.Set(vv.Header, vv.Context)
}
// request请求转换为字节流
b, err := httputil.DumpRequest(req, false)
if err != nil {
return
}
defer req.Body.Close()
// 判断协议,选择拨号流程
gconn, err := gtcp.NewPoolConn(websocketUrl.Host)
if err != nil {
return
}
// 向目标websocket服务发送握手包
_, err = gconn.Write(b)
if err != nil {
return
}
defer gconn.Close()
// 流量透传
var wg sync.WaitGroup
wg.Add(1)
go func() {
io.Copy(gconn, conn)
// conn has returned EOF or an error, so we need to shut down the
// other half of the duplex copy.
wg.Done()
}()
wg.Add(1)
go func() {
io.Copy(conn, gconn)
wg.Done()
}()
wg.Wait()
总结:
为老板降低成本,国内服务器太贵了。
但是网络速度全看aws,靠天吃饭,要是aws路线崩了,老板也就崩了。