Skip to content

Commit

Permalink
Merge pull request #4 from aak1247/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
aak1247 authored Nov 15, 2023
2 parents c512e25 + 4c2f1f6 commit 638a0c2
Show file tree
Hide file tree
Showing 6 changed files with 197 additions and 15 deletions.
9 changes: 5 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ require (
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.14.1 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/gorilla/websocket v1.5.1 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
github.com/leodido/go-urn v1.2.4 // indirect
Expand All @@ -23,10 +24,10 @@ require (
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
golang.org/x/arch v0.4.0 // indirect
golang.org/x/crypto v0.11.0 // indirect
golang.org/x/net v0.12.0 // indirect
golang.org/x/sys v0.10.0 // indirect
golang.org/x/text v0.11.0 // indirect
golang.org/x/crypto v0.15.0 // indirect
golang.org/x/net v0.18.0 // indirect
golang.org/x/sys v0.14.0 // indirect
golang.org/x/text v0.14.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
10 changes: 10 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MG
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
Expand Down Expand Up @@ -64,14 +66,22 @@ golang.org/x/arch v0.4.0 h1:A8WCeEWhLwPBKNbFi5Wv5UTCBx5zzubnXDlMOFAzFMc=
golang.org/x/arch v0.4.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA=
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA=
golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g=
golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50=
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4=
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
Expand Down
9 changes: 6 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package main

import (
"gproxy/proxy"
"log"
"os"
"strconv"
)

func main() {
// 解析命令行参数(httpProxy domain [-p port])
// 解析命令行参数(gproxy [-p port] [-m mode] domain
args := os.Args[1:]
if len(args) < 1 {
panic("invalid args")
Expand Down Expand Up @@ -35,8 +36,10 @@ func main() {
switch mode {
case "http":
// 启动HTTP代理服务
NewHttpProxy(domain, port)
proxy.NewHttpProxy(domain, port)
case "tcp":
NewTcpProxy(domain, port)
proxy.NewTcpProxy(domain, port)
case "ws":
proxy.NewWSProxy(domain, port)
}
}
2 changes: 1 addition & 1 deletion http.go → proxy/http.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main
package proxy

import (
"bytes"
Expand Down
14 changes: 7 additions & 7 deletions tcp.go → proxy/tcp.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main
package proxy

import (
"io"
Expand Down Expand Up @@ -52,15 +52,15 @@ func tcpProxy(url string, client net.Conn) error {
n, err := client.Read(buf)
if err != nil {
if err != io.EOF {
log.Printf("Failed to read from client: %v, close connection\n", err)
log.Printf("Failed to read from WSClient: %v, close connection\n", err)
cs <- true
ss <- true
return
}
}
if n > 0 {
log.Printf("received from client bytes %d\n", n)
log.Printf("Received data from client %s: %s\n", client.RemoteAddr().String(), string(buf[:n]))
log.Printf("received from WSClient bytes %d\n", n)
log.Printf("Received data from WSClient %s: %s\n", client.RemoteAddr().String(), string(buf[:n]))

// write to server
if n, err := server.Write(buf); err != nil {
Expand Down Expand Up @@ -101,11 +101,11 @@ func tcpProxy(url string, client net.Conn) error {
log.Printf("received from server bytes %d\n", n)
log.Printf("Received data from server %s: %s\n", server.RemoteAddr().String(), string(buf[:n]))

// write to client
// write to WSClient
if n, err := client.Write(buf); err != nil {
log.Println("Failed to write to client:", err)
log.Println("Failed to write to WSClient:", err)
} else {
log.Printf("write to client %d", n)
log.Printf("write to WSClient %d", n)
}
// 清空缓冲区
buf = make([]byte, 1024*256)
Expand Down
168 changes: 168 additions & 0 deletions proxy/ws.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
package proxy

import (
"fmt"
ws2 "github.com/gorilla/websocket"
"log"
"net/http"
"strconv"
"strings"
)

func NewWSProxy(url string, localPort int) {
//http.Handle("/proxyWsConn", )
http.HandleFunc("/", newWsProxy(url))
if err := http.ListenAndServe(":"+strconv.Itoa(localPort), nil); err != nil {
log.Fatalf("failed to start ws server\n")
}
}

func newWsProxy(url string) func(http.ResponseWriter, *http.Request) {
return func(writer http.ResponseWriter, request *http.Request) {
if ws2.IsWebSocketUpgrade(request) {
conn := initWSConn(writer, request)
// 拿到所有的header和参数
header := request.Header
requestUrl := request.URL
log.Printf("header %v", header)
log.Printf("url %v", requestUrl)
if url[len(url)-1] == '/' {
url = url[:len(url)-1]
}
targetUrl := url + requestUrl.Path
if len(requestUrl.RawQuery) != 0 {
targetUrl += "?" + requestUrl.RawQuery
}
proxyWsConn(conn, targetUrl, header)

// 代理访问
} else {
writer.Write([]byte("ok"))
}
}
}

func initWSConn(writer http.ResponseWriter, request *http.Request) *ws2.Conn {
var upgrader = ws2.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
CheckOrigin: func(r *http.Request) bool {
log.Println("升级协议", r.Header["User-Agent"])
return true
},
}
conn, err := upgrader.Upgrade(writer, request, nil)
if err != nil {
log.Println(err)
return nil
}
return conn
}

func proxyWsConn(ws *ws2.Conn, url string, headers http.Header) {
defer func() {
f := recover()
if f != nil {
fmt.Printf("fatal error %v\n", f)
}
}()
// WSClient init
server := &WSClient{}
if err := server.Connect(url, headers); err != nil {
log.Printf("connect error %v\n", err)
ws.Close()
return
}

// 上行 goroutine
go func() {
defer ws.Close()
defer server.Close()
defer func() {
if f := recover(); f != nil {
fmt.Printf("panic %v\n", f)
}
}()
for {
mt, message, err := ws.ReadMessage()
if err != nil {
if ce, ok := err.(*ws2.CloseError); ok && ws2.IsCloseError(ce, ce.Code) {
log.Printf("close error %v\n", err)
return
} else if strings.Contains(err.Error(), "use of closed network connection") {
log.Printf("close error %v\n", err)
return
} else {
log.Printf("read client message failed %v\n", err)
continue
}
}
log.Println("获取客户端发送的消息:" + string(message))
err = server.WriteMessage(mt, message)
if err != nil {
log.Printf("send message to server failed %v\n", err)
}
if mt == ws2.CloseMessage {
log.Printf("close message %s\n", string(message))
return
}
}
}()

// 下行 goroutine
go func() {
defer ws.Close()
defer server.Close()
defer func() {
if f := recover(); f != nil {
log.Printf("panic %v\n", f)
}
}()
for {
mt, message, err := server.ReadMessage()
if err != nil {
if ce, ok := err.(*ws2.CloseError); ok && ws2.IsCloseError(ce, ce.Code) {
log.Printf("close error %v\n", err)
return
} else if strings.Contains(err.Error(), "use of closed network connection") {
log.Printf("close error %v\n", err)
return
} else {
log.Printf("read server message failed %v\n", err)
continue
}
}
log.Println("获取服务器发送的消息:" + string(message))
err = ws.WriteMessage(mt, message)
if err != nil {
log.Printf("send message to client failed %v\n", err)
}
if mt == ws2.CloseMessage {
log.Printf("close message %s\n", string(message))
return
}
}
}()
}

type WSClient struct {
*ws2.Conn
}

func (cli *WSClient) Connect(url string, headers http.Header) error {
// delete dup header
headers.Del("Sec-WebSocket-Version")
headers.Del("Sec-WebSocket-Key")
headers.Del("Connection")
headers.Del("Upgrade")
headers.Del("Sec-Websocket-Extensions")
headers.Del("Sec-Websocket-Protocol")
conn, resp, err := ws2.DefaultDialer.Dial(url, headers)
if err != nil {
log.Printf("connect failed %v\n", err)
} else {
log.Printf("connect success %v\n", resp.Status)
cli.Conn = conn
}
return err
}

0 comments on commit 638a0c2

Please sign in to comment.