Skip to content

Commit

Permalink
v0.1.1
Browse files Browse the repository at this point in the history
Update Specify out local address.
Fix whitelist validation.
  • Loading branch information
hang666 committed Dec 5, 2022
1 parent 53ce7f5 commit 8cb9e9b
Show file tree
Hide file tree
Showing 7 changed files with 121 additions and 30 deletions.
13 changes: 10 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,22 @@

This software supports Windows/MacOS/Centos/Debian/Ubuntu and, in theory, all Linux.

- Support Multiple Validation
- Support for IP address whitelisting

The configuration file using YAML language.
Configuration file using YAML language.

Please fill in the template according to "config.yaml.example", and save it as "config.yaml".

You can also use the "--config" flag to customize the path to the config file.


## Features

- Full TCP/UDP support
- Multiple validation
- IP address whitelisting
- Specify out local address


## Install Script:

```bash
Expand Down
18 changes: 10 additions & 8 deletions config.yaml.example
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
accounts:
- username: "test"
password: "test123456"
bind_address: "0.0.0.0:8080"
req_address: ""
tcp_timeout: 60
udp_timeout: 60
whitelist:
- username: "test" # auth username
password: "test123456" # auth password
bind_address: "0.0.0.0:8080" # listen bind address + port
udp_bind_ip: "127.0.0.1" # udp bind ip
out_address: "192.168.100.165" # specify out local address
tcp_timeout: 60 # tcp timeout
udp_timeout: 60 # udp timeout
whitelist: # whitelist
- "192.168.100.1"
- "127.0.0.1"
- bind_address: "0.0.0.0:8081"
- bind_address: "0.0.0.0:8081" # bind 2
out_address: "" # auto out address
3 changes: 2 additions & 1 deletion server/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ type AccountStruct struct {
Username string `yaml:"username" mapstructure:"username"`
Password string `yaml:"password" mapstructure:"password"`
BindAddress string `yaml:"bind_address" mapstructure:"bind_address"`
ReqAddress string `yaml:"req_address" mapstructure:"req_address"`
OutAddress string `yaml:"out_address" mapstructure:"out_address"`
UDPBindIP string `yaml:"udp_bind_ip" mapstructure:"udp_bind_ip"`
Whitelist []string `yaml:"whitelist" mapstructure:"whitelist"`
TCPTimeout int `yaml:"tcp_timeout" mapstructure:"tcp_timeout"`
UDPTimeout int `yaml:"udp_timeout" mapstructure:"udp_timeout"`
Expand Down
19 changes: 3 additions & 16 deletions server/handle.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,34 +8,21 @@ import (
"strings"
"time"

"github.com/hang666/s5light/server/s5"
"github.com/txthinking/socks5"
)

type DefaultHandle struct {
whitelistMap WhitelistMapType
}

func checkIsWhitelisted(address string, whitelistMap WhitelistMapType) bool {
//log.Printf("client come in: %s", address)
w_map := whitelistMap
if len(w_map) == 0 {
return true
}
var ok bool
if strings.Contains(address, ":") {
_, ok = w_map[strings.Split(address, ":")[0]]
} else {
_, ok = w_map[address]
}
return ok
outAddress string
}

func (h *DefaultHandle) TCPHandle(s *socks5.Server, c *net.TCPConn, r *socks5.Request) error {
if !checkIsWhitelisted(c.RemoteAddr().String(), h.whitelistMap) {
return fmt.Errorf("%s is not whitelisted", c.RemoteAddr().String())
}
if r.Cmd == socks5.CmdConnect {
rc, err := r.Connect(c)
rc, err := s5.Connect(c, r, h.outAddress)
if err != nil {
return err
}
Expand Down
73 changes: 73 additions & 0 deletions server/s5/request.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package s5

import (
"io"
"log"
"net"

"github.com/txthinking/socks5"
)

// Connect remote conn which u want to connect with your dialer
// Error or OK both replied.
func Connect(w io.Writer, r *socks5.Request, outAddress string) (*net.TCPConn, error) {
if socks5.Debug {
log.Println("Call:", r.Address())
}
var tmp *net.TCPConn
var err error

tcpaddr, err := net.ResolveTCPAddr("tcp", r.Address())
if err != nil {
var p *socks5.Reply
if r.Atyp == socks5.ATYPIPv4 || r.Atyp == socks5.ATYPDomain {
p = socks5.NewReply(socks5.RepHostUnreachable, socks5.ATYPIPv4, []byte{0x00, 0x00, 0x00, 0x00}, []byte{0x00, 0x00})
} else {
p = socks5.NewReply(socks5.RepHostUnreachable, socks5.ATYPIPv6, []byte(net.IPv6zero), []byte{0x00, 0x00})
}
if _, err := p.WriteTo(w); err != nil {
return nil, err
}
return nil, err
}
if outAddress != "" {
localAddr, _ := net.ResolveTCPAddr("tcp", outAddress+":0")

tmp, err = socks5.Dial.DialTCP("tcp", localAddr, tcpaddr)

} else {
tmp, err = socks5.Dial.DialTCP("tcp", nil, tcpaddr)
}
if err != nil {
var p *socks5.Reply
if r.Atyp == socks5.ATYPIPv4 || r.Atyp == socks5.ATYPDomain {
p = socks5.NewReply(socks5.RepHostUnreachable, socks5.ATYPIPv4, []byte{0x00, 0x00, 0x00, 0x00}, []byte{0x00, 0x00})
} else {
p = socks5.NewReply(socks5.RepHostUnreachable, socks5.ATYPIPv6, []byte(net.IPv6zero), []byte{0x00, 0x00})
}
if _, err := p.WriteTo(w); err != nil {
return nil, err
}
return nil, err
}
rc := tmp
a, addr, port, err := socks5.ParseAddress(rc.LocalAddr().String())
if err != nil {
var p *socks5.Reply
if r.Atyp == socks5.ATYPIPv4 || r.Atyp == socks5.ATYPDomain {
p = socks5.NewReply(socks5.RepHostUnreachable, socks5.ATYPIPv4, []byte{0x00, 0x00, 0x00, 0x00}, []byte{0x00, 0x00})
} else {
p = socks5.NewReply(socks5.RepHostUnreachable, socks5.ATYPIPv6, []byte(net.IPv6zero), []byte{0x00, 0x00})
}
if _, err := p.WriteTo(w); err != nil {
return nil, err
}
return nil, err
}
p := socks5.NewReply(socks5.RepSuccess, a, addr, port)
if _, err := p.WriteTo(w); err != nil {
return nil, err
}

return rc, nil
}
5 changes: 3 additions & 2 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@ func listenAndServe() {
wg.Add(1)
go func(acc *AccountStruct) {
log.Printf("Server listening on %s", acc.BindAddress)
server, err := socks5.NewClassicServer(acc.BindAddress, acc.ReqAddress, acc.Username, acc.Password, acc.TCPTimeout, acc.UDPTimeout)
socks5.Debug = true
server, err := socks5.NewClassicServer(acc.BindAddress, acc.UDPBindIP, acc.Username, acc.Password, acc.TCPTimeout, acc.UDPTimeout)
if err != nil {
log.Panicln(err)
}
server.ListenAndServe(&DefaultHandle{acc.WhitelistMap})
server.ListenAndServe(&DefaultHandle{acc.WhitelistMap, acc.OutAddress})
wg.Done()
}(acc)
}
Expand Down
20 changes: 20 additions & 0 deletions server/util.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package server

import (
"net"
)

func checkIsWhitelisted(address string, whitelistMap WhitelistMapType) bool {
//log.Printf("client come in: %s", address)
w_map := whitelistMap
if len(w_map) == 0 {
return true
}
var ok bool
addr, _, err := net.SplitHostPort(address)
if err != nil {
addr = address
}
_, ok = w_map[addr]
return ok
}

0 comments on commit 8cb9e9b

Please sign in to comment.