Skip to content

Commit 06ee405

Browse files
committed
first commit
0 parents  commit 06ee405

30 files changed

+3215
-0
lines changed

.github/workflows/go.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
name: Go
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
pull_request:
7+
branches: [ main ]
8+
9+
jobs:
10+
11+
build:
12+
runs-on: ubuntu-latest
13+
steps:
14+
- uses: actions/checkout@v2
15+
16+
- name: Set up Go
17+
uses: actions/setup-go@v2
18+
with:
19+
go-version: 1.15
20+
21+
- name: Build
22+
run: go build -v ./...
23+
24+
- name: Test
25+
run: go test -v ./...

.github/workflows/gorelease.yml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
name: Release with goreleaser
2+
on:
3+
push:
4+
tags:
5+
- v*.*
6+
jobs:
7+
releases-matrix-windows:
8+
name: Release Go Binary for windows
9+
runs-on: ubuntu-latest
10+
strategy:
11+
matrix:
12+
goos: [windows]
13+
goarch: [amd64]
14+
steps:
15+
- uses: actions/checkout@v2
16+
- uses: wangyoucao577/go-release-action@v1.14
17+
with:
18+
github_token: ${{ secrets.GITHUB_TOKEN }}
19+
goos: ${{ matrix.goos }}
20+
goarch: ${{ matrix.goarch }}
21+
goversion: 1.16
22+
ldflags: "-s -w"
23+
24+
releases-matrix-linux:
25+
name: Release Go Binary for linux
26+
runs-on: ubuntu-latest
27+
strategy:
28+
matrix:
29+
goos: [linux]
30+
goarch: [386, amd64]
31+
steps:
32+
- uses: actions/checkout@v2
33+
- uses: wangyoucao577/go-release-action@v1.14
34+
with:
35+
github_token: ${{ secrets.GITHUB_TOKEN }}
36+
goos: ${{ matrix.goos }}
37+
goarch: ${{ matrix.goarch }}
38+
goversion: 1.16
39+
ldflags: "-s -w"

README.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
Router socks
2+
======
3+
4+
The idea came after using [chisel](https://github.com/jpillora/chisel). Chisel is really helpful but it can get hard to manage many clients as it is opening a new socks port for each new client with reverse mode.
5+
6+
![Schema](./images/schema.png)
7+
8+
## Usage
9+
10+
Start the socks server:
11+
12+
```
13+
Usage:
14+
rsocks [flags]
15+
16+
Flags:
17+
-h, --help help for rsocks
18+
-i, --ip string IP for socks5 server (default "0.0.0.0")
19+
-p, --port int Socks5 port (default 1080)
20+
```
21+
Define the routes:
22+
```
23+
RouterSocks> help
24+
route: Manage route to socks servers
25+
chisel: Liste chisel socks server on localhost
26+
help: help command
27+
RouterSocks> route add 192.168.1.0/24 10.0.0.1:1081
28+
[*] Successfull route added
29+
RouterSocks> chisel
30+
[0] 127.0.0.1:1081
31+
RouterSocks> route add 192.168.2.0/24 0
32+
[*] Successfull route added
33+
RouterSocks> route
34+
192.168.1.0/24 => 10.0.0.1:1081
35+
192.168.2.0/24 => 127.0.0.1:1081
36+
```
37+
38+
## Features
39+
- Route network through remote or local socks server
40+
- Use chisel session ID

cmd/root.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package cmd
2+
3+
import (
4+
"fmt"
5+
"os"
6+
7+
"github.com/spf13/cobra"
8+
9+
prompt "github.com/nodauf/Go-RouterSocks/prompt"
10+
socks "github.com/nodauf/Go-RouterSocks/socks"
11+
)
12+
13+
var cfgFile string
14+
var port int
15+
var ip string
16+
17+
var rootCmd = &cobra.Command{
18+
Use: "rsocks",
19+
Short: "Router socks",
20+
Long: `Run a socks server and redirect the traffic to other socks server
21+
according of the defined routes.`,
22+
Run: func(cmd *cobra.Command, args []string) {
23+
socks.StartSocks(ip, port)
24+
prompt.Prompt()
25+
},
26+
}
27+
28+
func Execute() {
29+
if err := rootCmd.Execute(); err != nil {
30+
fmt.Println(err)
31+
os.Exit(1)
32+
}
33+
}
34+
35+
func init() {
36+
37+
rootCmd.Flags().IntVarP(
38+
&port, "port", "p", 1080,
39+
"Socks5 port",
40+
)
41+
rootCmd.Flags().StringVarP(
42+
&ip, "ip", "i", "0.0.0.0",
43+
"IP for socks5 server",
44+
)
45+
}

go-socks5/README.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
go-socks5 [![Build Status](https://travis-ci.org/armon/go-socks5.png)](https://travis-ci.org/armon/go-socks5)
2+
=========
3+
4+
Provides the `socks5` package that implements a [SOCKS5 server](http://en.wikipedia.org/wiki/SOCKS).
5+
SOCKS (Secure Sockets) is used to route traffic between a client and server through
6+
an intermediate proxy layer. This can be used to bypass firewalls or NATs.
7+
8+
Feature
9+
=======
10+
11+
The package has the following features:
12+
* "No Auth" mode
13+
* User/Password authentication
14+
* Support for the CONNECT command
15+
* Rules to do granular filtering of commands
16+
* Custom DNS resolution
17+
* Unit tests
18+
19+
TODO
20+
====
21+
22+
The package still needs the following:
23+
* Support for the BIND command
24+
* Support for the ASSOCIATE command
25+
26+
27+
Example
28+
=======
29+
30+
Below is a simple example of usage
31+
32+
```go
33+
// Create a SOCKS5 server
34+
conf := &socks5.Config{}
35+
server, err := socks5.New(conf)
36+
if err != nil {
37+
panic(err)
38+
}
39+
40+
// Create SOCKS5 proxy on localhost port 8000
41+
if err := server.ListenAndServe("tcp", "127.0.0.1:8000"); err != nil {
42+
panic(err)
43+
}
44+
```
45+

go-socks5/auth.go

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
package socks5
2+
3+
import (
4+
"fmt"
5+
"io"
6+
)
7+
8+
const (
9+
NoAuth = uint8(0)
10+
noAcceptable = uint8(255)
11+
UserPassAuth = uint8(2)
12+
userAuthVersion = uint8(1)
13+
authSuccess = uint8(0)
14+
authFailure = uint8(1)
15+
)
16+
17+
var (
18+
UserAuthFailed = fmt.Errorf("User authentication failed")
19+
NoSupportedAuth = fmt.Errorf("No supported authentication mechanism")
20+
)
21+
22+
// A Request encapsulates authentication state provided
23+
// during negotiation
24+
type AuthContext struct {
25+
// Provided auth method
26+
Method uint8
27+
// Payload provided during negotiation.
28+
// Keys depend on the used auth method.
29+
// For UserPassauth contains Username
30+
Payload map[string]string
31+
}
32+
33+
type Authenticator interface {
34+
Authenticate(reader io.Reader, writer io.Writer) (*AuthContext, error)
35+
GetCode() uint8
36+
}
37+
38+
// NoAuthAuthenticator is used to handle the "No Authentication" mode
39+
type NoAuthAuthenticator struct{}
40+
41+
func (a NoAuthAuthenticator) GetCode() uint8 {
42+
return NoAuth
43+
}
44+
45+
func (a NoAuthAuthenticator) Authenticate(reader io.Reader, writer io.Writer) (*AuthContext, error) {
46+
_, err := writer.Write([]byte{socks5Version, NoAuth})
47+
return &AuthContext{NoAuth, nil}, err
48+
}
49+
50+
// UserPassAuthenticator is used to handle username/password based
51+
// authentication
52+
type UserPassAuthenticator struct {
53+
Credentials CredentialStore
54+
}
55+
56+
func (a UserPassAuthenticator) GetCode() uint8 {
57+
return UserPassAuth
58+
}
59+
60+
func (a UserPassAuthenticator) Authenticate(reader io.Reader, writer io.Writer) (*AuthContext, error) {
61+
// Tell the client to use user/pass auth
62+
if _, err := writer.Write([]byte{socks5Version, UserPassAuth}); err != nil {
63+
return nil, err
64+
}
65+
66+
// Get the version and username length
67+
header := []byte{0, 0}
68+
if _, err := io.ReadAtLeast(reader, header, 2); err != nil {
69+
return nil, err
70+
}
71+
72+
// Ensure we are compatible
73+
if header[0] != userAuthVersion {
74+
return nil, fmt.Errorf("Unsupported auth version: %v", header[0])
75+
}
76+
77+
// Get the user name
78+
userLen := int(header[1])
79+
user := make([]byte, userLen)
80+
if _, err := io.ReadAtLeast(reader, user, userLen); err != nil {
81+
return nil, err
82+
}
83+
84+
// Get the password length
85+
if _, err := reader.Read(header[:1]); err != nil {
86+
return nil, err
87+
}
88+
89+
// Get the password
90+
passLen := int(header[0])
91+
pass := make([]byte, passLen)
92+
if _, err := io.ReadAtLeast(reader, pass, passLen); err != nil {
93+
return nil, err
94+
}
95+
96+
// Verify the password
97+
if a.Credentials.Valid(string(user), string(pass)) {
98+
if _, err := writer.Write([]byte{userAuthVersion, authSuccess}); err != nil {
99+
return nil, err
100+
}
101+
} else {
102+
if _, err := writer.Write([]byte{userAuthVersion, authFailure}); err != nil {
103+
return nil, err
104+
}
105+
return nil, UserAuthFailed
106+
}
107+
108+
// Done
109+
return &AuthContext{UserPassAuth, map[string]string{"Username": string(user)}}, nil
110+
}
111+
112+
// authenticate is used to handle connection authentication
113+
func (s *Server) authenticate(conn io.Writer, bufConn io.Reader) ([]byte, *AuthContext, error) {
114+
// Get the methods
115+
methods, err := readMethods(bufConn)
116+
if err != nil {
117+
return nil, nil, fmt.Errorf("Failed to get auth methods: %v", err)
118+
}
119+
120+
// Select a usable method
121+
for _, method := range methods {
122+
cator, found := s.authMethods[method]
123+
if found {
124+
authContext, err := cator.Authenticate(bufConn, conn)
125+
return methods, authContext, err
126+
}
127+
}
128+
129+
// No usable method found
130+
return nil, nil, noAcceptableAuth(conn)
131+
}
132+
133+
// noAcceptableAuth is used to handle when we have no eligible
134+
// authentication mechanism
135+
func noAcceptableAuth(conn io.Writer) error {
136+
conn.Write([]byte{socks5Version, noAcceptable})
137+
return NoSupportedAuth
138+
}
139+
140+
// readMethods is used to read the number of methods
141+
// and proceeding auth methods
142+
func readMethods(r io.Reader) ([]byte, error) {
143+
header := []byte{0}
144+
if _, err := r.Read(header); err != nil {
145+
return nil, err
146+
}
147+
148+
numMethods := int(header[0])
149+
methods := make([]byte, numMethods)
150+
_, err := io.ReadAtLeast(r, methods, numMethods)
151+
return methods, err
152+
}

0 commit comments

Comments
 (0)