Merge pull request #43 from sazonovanton/master
Added IP whitelist support
This commit is contained in:
commit
d6a5236865
@ -19,6 +19,12 @@ Leave `PROXY_USER` and `PROXY_PASSWORD` empty for skip authentication options wh
|
|||||||
|PROXY_PASSWORD|String|EMPTY|Set proxy password for auth, used with PROXY_USER|
|
|PROXY_PASSWORD|String|EMPTY|Set proxy password for auth, used with PROXY_USER|
|
||||||
|PROXY_PORT|String|1080|Set listen port for application inside docker container|
|
|PROXY_PORT|String|1080|Set listen port for application inside docker container|
|
||||||
|TZ|String|UTC|Set Timezone like in many common Operation Systems|
|
|TZ|String|UTC|Set Timezone like in many common Operation Systems|
|
||||||
|
|ALLOWED_IPS|String|Empty|Set allowed IP's that can connect to proxy, separator `,`|
|
||||||
|
|
||||||
|
`ALLOWED_IPS` parameter is not included in `serjs/go-socks5-proxy` image.\
|
||||||
|
You can build your image with:
|
||||||
|
`docker-compose -f docker-compose.build.yml up -d`\
|
||||||
|
Just don't forget to set parameters in the `.env` file.
|
||||||
|
|
||||||
## Test running service
|
## Test running service
|
||||||
|
|
||||||
|
11
docker-compose.build.yml
Normal file
11
docker-compose.build.yml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
version: '3'
|
||||||
|
services:
|
||||||
|
socks5-build:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
container_name: socks5-build
|
||||||
|
env_file: .env
|
||||||
|
ports:
|
||||||
|
- "1080:1080"
|
||||||
|
restart: unless-stopped
|
11
server.go
11
server.go
@ -2,6 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
|
"net"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/armon/go-socks5"
|
"github.com/armon/go-socks5"
|
||||||
@ -12,6 +13,7 @@ type params struct {
|
|||||||
User string `env:"PROXY_USER" envDefault:""`
|
User string `env:"PROXY_USER" envDefault:""`
|
||||||
Password string `env:"PROXY_PASSWORD" envDefault:""`
|
Password string `env:"PROXY_PASSWORD" envDefault:""`
|
||||||
Port string `env:"PROXY_PORT" envDefault:"1080"`
|
Port string `env:"PROXY_PORT" envDefault:"1080"`
|
||||||
|
AllowedIPs []string `env:"ALLOWED_IPS" envSeparator:"," envDefault:""`
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@ -40,6 +42,15 @@ func main() {
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set IP whitelist
|
||||||
|
if len(cfg.AllowedIPs) > 0 {
|
||||||
|
whitelist := make([]net.IP, len(cfg.AllowedIPs))
|
||||||
|
for i, ip := range cfg.AllowedIPs {
|
||||||
|
whitelist[i] = net.ParseIP(ip)
|
||||||
|
}
|
||||||
|
server.SetIPWhitelist(whitelist)
|
||||||
|
}
|
||||||
|
|
||||||
log.Printf("Start listening proxy service on port %s\n", cfg.Port)
|
log.Printf("Start listening proxy service on port %s\n", cfg.Port)
|
||||||
if err := server.ListenAndServe("tcp", ":"+cfg.Port); err != nil {
|
if err := server.ListenAndServe("tcp", ":"+cfg.Port); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
32
vendor/github.com/armon/go-socks5/socks5.go
generated
vendored
32
vendor/github.com/armon/go-socks5/socks5.go
generated
vendored
@ -55,6 +55,7 @@ type Config struct {
|
|||||||
type Server struct {
|
type Server struct {
|
||||||
config *Config
|
config *Config
|
||||||
authMethods map[uint8]Authenticator
|
authMethods map[uint8]Authenticator
|
||||||
|
isIPAllowed func(net.IP) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new Server and potentially returns an error
|
// New creates a new Server and potentially returns an error
|
||||||
@ -93,6 +94,11 @@ func New(conf *Config) (*Server, error) {
|
|||||||
server.authMethods[a.GetCode()] = a
|
server.authMethods[a.GetCode()] = a
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set default IP whitelist function
|
||||||
|
server.isIPAllowed = func(ip net.IP) bool {
|
||||||
|
return true // default allow all IPs
|
||||||
|
}
|
||||||
|
|
||||||
return server, nil
|
return server, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,11 +123,37 @@ func (s *Server) Serve(l net.Listener) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetIPWhitelist sets the function to check if a given IP is allowed
|
||||||
|
func (s *Server) SetIPWhitelist(allowedIPs []net.IP) {
|
||||||
|
s.isIPAllowed = func(ip net.IP) bool {
|
||||||
|
for _, allowedIP := range allowedIPs {
|
||||||
|
if ip.Equal(allowedIP) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ServeConn is used to serve a single connection.
|
// ServeConn is used to serve a single connection.
|
||||||
func (s *Server) ServeConn(conn net.Conn) error {
|
func (s *Server) ServeConn(conn net.Conn) error {
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
bufConn := bufio.NewReader(conn)
|
bufConn := bufio.NewReader(conn)
|
||||||
|
|
||||||
|
// Check client IP against whitelist
|
||||||
|
clientIP, _, err := net.SplitHostPort(conn.RemoteAddr().String())
|
||||||
|
if err != nil {
|
||||||
|
s.config.Logger.Printf("[ERR] socks: Failed to get client IP address: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ip := net.ParseIP(clientIP)
|
||||||
|
if s.isIPAllowed(ip) {
|
||||||
|
s.config.Logger.Printf("[INFO] socks: Connection from allowed IP address: %s", clientIP)
|
||||||
|
} else {
|
||||||
|
s.config.Logger.Printf("[WARN] socks: Connection from not allowed IP address: %s", clientIP)
|
||||||
|
return fmt.Errorf("connection from not allowed IP address")
|
||||||
|
}
|
||||||
|
|
||||||
// Read the version byte
|
// Read the version byte
|
||||||
version := []byte{0}
|
version := []byte{0}
|
||||||
if _, err := bufConn.Read(version); err != nil {
|
if _, err := bufConn.Read(version); err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user