├── .github └── workflows │ └── go.yml ├── .gitignore ├── Dockerfile ├── LICENSE ├── README.md ├── go.mod ├── main.go └── pack.sh /.github/workflows/go.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a golang project 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go 3 | 4 | name: Go 5 | 6 | on: 7 | push: 8 | branches: [ "master" ] 9 | pull_request: 10 | branches: [ "master" ] 11 | 12 | jobs: 13 | 14 | build: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@v3 18 | 19 | - name: Set up Go 20 | uses: actions/setup-go@v3 21 | with: 22 | go-version: 1.19 23 | 24 | - name: Build 25 | run: | 26 | go mod tidy 27 | go build -v ./... 28 | 29 | - name: Test 30 | run: go test -v ./... 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, built with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | # Dependency directories (remove the comment below to include it) 15 | # vendor/ 16 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang AS build-env 2 | 3 | RUN GO111MODULE=off go get -u github.com/esrrhs/socksserver 4 | RUN GO111MODULE=off go get -u github.com/esrrhs/socksserver/... 5 | RUN GO111MODULE=off go install github.com/esrrhs/socksserver 6 | 7 | FROM debian 8 | COPY --from=build-env /go/bin/socksserver . 9 | WORKDIR ./ 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 zhao xin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # socksserver 2 | 3 | [](https://github.com/esrrhs/socksserver) 4 | [](https://github.com/esrrhs/socksserver) 5 | [![Go Report Card](https://goreportcard.com/badge/github.com/esrrhs/socksserver)](https://goreportcard.com/report/github.com/esrrhs/socksserver) 6 | [](https://github.com/esrrhs/socksserver/releases) 7 | [](https://github.com/esrrhs/socksserver/releases) 8 | [](https://hub.docker.com/repository/docker/esrrhs/socksserver) 9 | [](https://github.com/esrrhs/socksserver/actions) 10 | 11 | 简单的socks5服务器 12 | ``` 13 | ./socksserver -l :4455 14 | ``` 15 | docker 16 | ``` 17 | docker run --name socksserver -d --privileged --network host --restart=always esrrhs/socksserver ./socksserver -u yourusername -p yourpassword -l :1080 18 | ``` 19 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/esrrhs/socksserver 2 | 3 | go 1.19 4 | 5 | require github.com/esrrhs/gohome v0.0.0-20230222132228-8bb1d3e2ecc4 6 | 7 | require ( 8 | github.com/OneOfOne/xxhash v1.2.8 // indirect 9 | github.com/google/uuid v1.3.0 // indirect 10 | google.golang.org/protobuf v1.33.0 // indirect 11 | ) 12 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "github.com/esrrhs/gohome/common" 6 | "github.com/esrrhs/gohome/loggo" 7 | "github.com/esrrhs/gohome/network" 8 | "io" 9 | "net" 10 | ) 11 | 12 | func main() { 13 | 14 | defer common.CrashLog() 15 | 16 | listen := flag.String("l", "", "listen addr") 17 | nolog := flag.Int("nolog", 0, "write log file") 18 | noprint := flag.Int("noprint", 0, "print stdout") 19 | loglevel := flag.String("loglevel", "info", "log level") 20 | user := flag.String("u", "", "username") 21 | password := flag.String("p", "", "password") 22 | 23 | flag.Parse() 24 | 25 | if *listen == "" { 26 | flag.Usage() 27 | return 28 | } 29 | 30 | level := loggo.LEVEL_INFO 31 | if loggo.NameToLevel(*loglevel) >= 0 { 32 | level = loggo.NameToLevel(*loglevel) 33 | } 34 | loggo.Ini(loggo.Config{ 35 | Level: level, 36 | Prefix: "socksserver", 37 | MaxDay: 3, 38 | NoLogFile: *nolog > 0, 39 | NoPrint: *noprint > 0, 40 | }) 41 | loggo.Info("start...") 42 | 43 | tcpaddr, err := net.ResolveTCPAddr("tcp", *listen) 44 | if err != nil { 45 | loggo.Error("listen fail %s", err) 46 | return 47 | } 48 | 49 | tcplistenConn, err := net.ListenTCP("tcp", tcpaddr) 50 | if err != nil { 51 | loggo.Error("Error listening for tcp packets: %s", err) 52 | return 53 | } 54 | loggo.Info("listen ok %s", tcpaddr.String()) 55 | 56 | for { 57 | conn, err := tcplistenConn.AcceptTCP() 58 | if err != nil { 59 | loggo.Info("Error accept tcp %s", err) 60 | continue 61 | } 62 | 63 | go process(conn, *user, *password) 64 | } 65 | } 66 | 67 | func process(conn *net.TCPConn, user string, password string) { 68 | 69 | defer common.CrashLog() 70 | 71 | var err error = nil 72 | if err = network.Sock5HandshakeBy(conn, user, password); err != nil { 73 | loggo.Error("socks handshake: %s", err) 74 | conn.Close() 75 | return 76 | } 77 | _, targetAddr, err := network.Sock5GetRequest(conn) 78 | if err != nil { 79 | loggo.Error("error getting request: %s", err) 80 | conn.Close() 81 | return 82 | } 83 | // Sending connection established message immediately to client. 84 | // This some round trip time for creating socks connection with the client. 85 | // But if connection failed, the client will get connection reset error. 86 | _, err = conn.Write([]byte{0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x43}) 87 | if err != nil { 88 | loggo.Error("send connection confirmation: %s", err) 89 | conn.Close() 90 | return 91 | } 92 | 93 | loggo.Info("accept new sock5 conn: %s", targetAddr) 94 | 95 | tcpsrcaddr := conn.RemoteAddr().(*net.TCPAddr) 96 | 97 | loggo.Info("client accept new direct local tcp %s %s", tcpsrcaddr.String(), targetAddr) 98 | 99 | tcpaddrTarget, err := net.ResolveTCPAddr("tcp", targetAddr) 100 | if err != nil { 101 | loggo.Info("direct local tcp ResolveTCPAddr fail: %s %s", targetAddr, err.Error()) 102 | return 103 | } 104 | 105 | targetconn, err := net.DialTCP("tcp", nil, tcpaddrTarget) 106 | if err != nil { 107 | loggo.Info("direct local tcp DialTCP fail: %s %s", targetAddr, err.Error()) 108 | return 109 | } 110 | 111 | go transfer(conn, targetconn, conn.RemoteAddr().String(), targetconn.RemoteAddr().String()) 112 | go transfer(targetconn, conn, targetconn.RemoteAddr().String(), conn.RemoteAddr().String()) 113 | 114 | loggo.Info("client accept new direct local tcp ok %s %s", tcpsrcaddr.String(), targetAddr) 115 | } 116 | 117 | func transfer(destination io.WriteCloser, source io.ReadCloser, dst string, src string) { 118 | 119 | defer common.CrashLog() 120 | 121 | defer destination.Close() 122 | defer source.Close() 123 | loggo.Info("client begin transfer from %s -> %s", src, dst) 124 | io.Copy(destination, source) 125 | loggo.Info("client end transfer from %s -> %s", src, dst) 126 | } 127 | -------------------------------------------------------------------------------- /pack.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | #set -x 3 | NAME="socksserver" 4 | 5 | export GO111MODULE=on 6 | 7 | #go tool dist list 8 | build_list=$(go tool dist list) 9 | 10 | rm pack -rf 11 | rm pack.zip -f 12 | mkdir pack 13 | 14 | for line in $build_list; do 15 | os=$(echo "$line" | awk -F"/" '{print $1}') 16 | arch=$(echo "$line" | awk -F"/" '{print $2}') 17 | echo "os="$os" arch="$arch" start build" 18 | if [ $os == "android" ]; then 19 | continue 20 | fi 21 | if [ $os == "ios" ]; then 22 | continue 23 | fi 24 | if [ $arch == "wasm" ]; then 25 | continue 26 | fi 27 | CGO_ENABLED=0 GOOS=$os GOARCH=$arch go build -ldflags="-s -w" 28 | if [ $? -ne 0 ]; then 29 | echo "os="$os" arch="$arch" build fail" 30 | exit 1 31 | fi 32 | if [ $os = "windows" ]; then 33 | zip ${NAME}_"${os}"_"${arch}"".zip" $NAME".exe" 34 | if [ $? -ne 0 ]; then 35 | echo "os="$os" arch="$arch" zip fail" 36 | exit 1 37 | fi 38 | mv ${NAME}_"${os}"_"${arch}"".zip" pack/ 39 | rm $NAME".exe" -f 40 | else 41 | zip ${NAME}_"${os}"_"${arch}"".zip" $NAME 42 | if [ $? -ne 0 ]; then 43 | echo "os="$os" arch="$arch" zip fail" 44 | exit 1 45 | fi 46 | mv ${NAME}_"${os}"_"${arch}"".zip" pack/ 47 | rm $NAME -f 48 | fi 49 | echo "os="$os" arch="$arch" done build" 50 | done 51 | 52 | zip pack.zip pack/ -r 53 | 54 | echo "all done" 55 | --------------------------------------------------------------------------------