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路线崩了,老板也就崩了。


Preview Image