├── .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 | [](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 |
--------------------------------------------------------------------------------