Compare commits
10
Commits
b719edd920
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
13b66aeea6 | ||
|
|
3c8d31b9e9 | ||
|
|
38627992d9 | ||
|
|
f1cd03ff76 | ||
|
|
1cdfcea4ad | ||
|
|
1f5e188a14 | ||
|
|
14bdfbb6a2 | ||
|
|
f0eb61962e | ||
|
|
4298d972a9 | ||
|
|
7cabaad451 |
@@ -0,0 +1,9 @@
|
|||||||
|
# Authentication is enabled by default. Change these before production use.
|
||||||
|
REQUIRE_AUTH=true
|
||||||
|
PROXY_USER=socksuser
|
||||||
|
PROXY_PASSWORD=change-me-please
|
||||||
|
PROXY_PORT=1080
|
||||||
|
|
||||||
|
# Optional filters. Empty means allow all.
|
||||||
|
ALLOWED_DEST_FQDN=
|
||||||
|
ALLOWED_IPS=
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
.env
|
||||||
|
*.log
|
||||||
|
.DS_Store
|
||||||
+14
-5
@@ -3,12 +3,21 @@ All notable changes to this project will be documented in this file.
|
|||||||
|
|
||||||
## [Unreleased - available on :latest tag for docker image]
|
## [Unreleased - available on :latest tag for docker image]
|
||||||
### Changed
|
### Changed
|
||||||
- Migrate to distroless docker image from scratch
|
|
||||||
-
|
|
||||||
### Added
|
### Added
|
||||||
- New ALLOWED_DEST_FQDN config env paramteter for filtering dest FQND based on regex patterns
|
|
||||||
- New SetIPWhitelist config env paramteter for setting whitelist set of ip addresses which allowed to use proxy connection
|
## [v0.0.4] - 2025-10-07
|
||||||
- Dependabot version updates automation
|
|
||||||
|
**Important:** :warning: Starting with this release, the proxy requires authentication by default. The `REQUIRE_AUTH` parameter is now set to `true` by default. Please refer to the documentation for details on this change.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Migrated to a distroless Docker image from scratch.
|
||||||
|
- Moved go-socks5 to a modified forked repository at https://github.com/serjs/go-socks5 as a dependency.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Added `REQUIRE_AUTH` parameter with a default value of `true` to enforce authentication for the proxy.
|
||||||
|
- Added `ALLOWED_DEST_FQDN` config environment parameter for filtering destination FQDNs based on regex patterns.
|
||||||
|
- Added `SetIPWhitelist` config environment parameter for setting a whitelist of IP addresses allowed to use the proxy connection.
|
||||||
|
- Implemented Dependabot version updates automation.
|
||||||
|
|
||||||
## [v0.0.3] - 2021-07-07
|
## [v0.0.3] - 2021-07-07
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
ARG GOLANG_VERSION="1.19.1"
|
ARG GOLANG_VERSION="1.25"
|
||||||
|
|
||||||
FROM golang:$GOLANG_VERSION-alpine as builder
|
FROM golang:$GOLANG_VERSION-alpine as builder
|
||||||
RUN apk --no-cache add tzdata
|
RUN apk --no-cache add tzdata
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2025 Sergey Bogatyrets
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
# serjs/socks5-server LAN IP deployment
|
||||||
|
|
||||||
|
This folder contains compose examples for running `serjs/go-socks5-proxy`.
|
||||||
|
|
||||||
|
## Important finding on this Mac / OrbStack host
|
||||||
|
|
||||||
|
The Mac is on LAN `192.168.2.0/24` as `192.168.2.69`.
|
||||||
|
Docker is running inside OrbStack, whose Docker daemon network interface is `198.19.249.2/24`, not the physical `en0` LAN interface.
|
||||||
|
|
||||||
|
Because of that, Docker `macvlan`/`ipvlan` cannot attach directly to macOS `en0` from inside OrbStack. In testing, Compose can create a macvlan container with metadata IP `192.168.2.200`, but the Mac/LAN cannot ARP or connect to it (`192.168.2.200:1080` times out and ARP stays incomplete). So a true same-LAN container IP is normally feasible on a native Linux host with a real NIC, but not directly on this current macOS/OrbStack setup via only docker-compose.
|
||||||
|
|
||||||
|
## Recommended on this Mac: host-published port
|
||||||
|
|
||||||
|
Use `docker-compose.yml`. It runs the SOCKS5 server and publishes port `1080` on the Mac:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp .env.example .env
|
||||||
|
# edit .env
|
||||||
|
# then:
|
||||||
|
docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
Access from LAN:
|
||||||
|
|
||||||
|
```text
|
||||||
|
192.168.2.69:1080
|
||||||
|
```
|
||||||
|
|
||||||
|
## Real LAN IP version for a Linux host
|
||||||
|
|
||||||
|
Use `docker-compose.macvlan-linux.yml` on a Linux machine physically connected to `192.168.2.0/24`.
|
||||||
|
|
||||||
|
Before using it:
|
||||||
|
|
||||||
|
1. Make sure `192.168.2.200` is outside DHCP range or reserved for this container.
|
||||||
|
2. Replace `parent: eth0` with the Linux host NIC name.
|
||||||
|
3. Confirm the intended default gateway. In this chat BOSS asked for `192.168.2.1`, but this Mac's current default gateway is `192.168.2.8`.
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose -f docker-compose.macvlan-linux.yml up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
Access:
|
||||||
|
|
||||||
|
```text
|
||||||
|
192.168.2.200:1080
|
||||||
|
```
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
# go-socks5-proxy
|
# go-socks5-proxy
|
||||||
|
|
||||||

|

|
||||||

|
|
||||||
|
|
||||||
Simple socks5 server using go-socks5 with authentication, allowed ips list and destination FQDNs filtering
|
Simple socks5 server using go-socks5 with authentication, allowed ips list and destination FQDNs filtering
|
||||||
|
|
||||||
@@ -11,16 +10,15 @@ Simple socks5 server using go-socks5 with authentication, allowed ips list and d
|
|||||||
|
|
||||||
```docker run -d --name socks5 -p 1080:1080 -e PROXY_USER=<PROXY_USER> -e PROXY_PASSWORD=<PROXY_PASSWORD> serjs/go-socks5-proxy```
|
```docker run -d --name socks5 -p 1080:1080 -e PROXY_USER=<PROXY_USER> -e PROXY_PASSWORD=<PROXY_PASSWORD> serjs/go-socks5-proxy```
|
||||||
|
|
||||||
- Leave `PROXY_USER` and `PROXY_PASSWORD` empty for skip authentication options while running socks5 server, see example below
|
- Run docker container using specific container port and expose it to host port 1090
|
||||||
|
|
||||||
- Run docker container using specifit container port and expose it to host port 1090, without auth creds
|
```docker run -d --name socks5 -p 1090:9090 -e PROXY_USER=<PROXY_USER> -e PROXY_PASSWORD=<PROXY_PASSWORD> -e PROXY_PORT=9090 serjs/go-socks5-proxy```
|
||||||
|
|
||||||
```docker run -d --name socks5 -p 1090:9090 -e PROXY_PORT=9090 serjs/go-socks5-proxy```
|
|
||||||
|
|
||||||
# List of supported config parameters
|
# List of supported config parameters
|
||||||
|
|
||||||
|ENV variable|Type|Default|Description|
|
|ENV variable|Type|Default|Description|
|
||||||
|------------|----|-------|-----------|
|
|------------|----|-------|-----------|
|
||||||
|
|REQUIRE_AUTH|String|true|Allow accepting socks5 connections without auth creds. Not recommended untill you use other protections mechanisms like Whitelists Subnets using Firewall or Proxy itself|
|
||||||
|PROXY_USER|String|EMPTY|Set proxy user (also required existed PROXY_PASS)|
|
|PROXY_USER|String|EMPTY|Set proxy user (also required existed PROXY_PASS)|
|
||||||
|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|
|
||||||
@@ -30,7 +28,7 @@ Simple socks5 server using go-socks5 with authentication, allowed ips list and d
|
|||||||
|
|
||||||
# Build your own image:
|
# Build your own image:
|
||||||
`docker-compose -f docker-compose.build.yml up -d`\
|
`docker-compose -f docker-compose.build.yml up -d`\
|
||||||
Just don't forget to set parameters in the `.env` file.
|
Just don't forget to set parameters in the `.env` file (`cp .env.example .env)` and edit it with your config parameters
|
||||||
|
|
||||||
# Test running service
|
# Test running service
|
||||||
|
|
||||||
@@ -38,19 +36,19 @@ Assuming that you are using container on 1080 host docker port
|
|||||||
|
|
||||||
## Without authentication
|
## Without authentication
|
||||||
|
|
||||||
```curl --socks5 <docker host ip>:1080 https://ifcfg.co``` - result must show docker host ip (for bridged network)
|
```curl --socks5 <docker host ip>:1080 https://ipinfo.io``` - result must show docker host ip (for bridged network)
|
||||||
|
|
||||||
or
|
or
|
||||||
|
|
||||||
```docker run --rm curlimages/curl:7.65.3 -s --socks5 <docker host ip>:1080 https://ifcfg.co```
|
```docker run --rm curlimages/curl:7.65.3 -s --socks5 <docker host ip>:1080 https://ipinfo.io```
|
||||||
|
|
||||||
## With authentication
|
## With authentication
|
||||||
|
|
||||||
```curl --socks5 <docker host ip>:1080 -U <PROXY_USER>:<PROXY_PASSWORD> http://ifcfg.co```
|
```curl --socks5 <docker host ip>:1080 -U <PROXY_USER>:<PROXY_PASSWORD> https://ipinfo.io```
|
||||||
|
|
||||||
or
|
or
|
||||||
|
|
||||||
```docker run --rm curlimages/curl:7.65.3 -s --socks5 <PROXY_USER>:<PROXY_PASSWORD>@<docker host ip>:1080 http://ifcfg.co```
|
```docker run --rm curlimages/curl:7.65.3 -s --socks5 <PROXY_USER>:<PROXY_PASSWORD>@<docker host ip>:1080 https://ipinfo.io```
|
||||||
|
|
||||||
# Authors
|
# Authors
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
# Alternative for native Linux Docker hosts. ipvlan L2 often works better than
|
||||||
|
# macvlan on switches/APs that dislike multiple MAC addresses behind one port.
|
||||||
|
# Not expected to work directly on macOS OrbStack for the same VM/NIC reason.
|
||||||
|
|
||||||
|
services:
|
||||||
|
socks5:
|
||||||
|
image: serjs/go-socks5-proxy:latest
|
||||||
|
container_name: socks5-server-lan
|
||||||
|
restart: unless-stopped
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
networks:
|
||||||
|
socks5_lan:
|
||||||
|
ipv4_address: 192.168.2.200
|
||||||
|
|
||||||
|
networks:
|
||||||
|
socks5_lan:
|
||||||
|
driver: ipvlan
|
||||||
|
driver_opts:
|
||||||
|
parent: eth0
|
||||||
|
ipvlan_mode: l2
|
||||||
|
ipam:
|
||||||
|
config:
|
||||||
|
- subnet: 192.168.2.0/24
|
||||||
|
gateway: 192.168.2.1
|
||||||
|
ip_range: 192.168.2.200/32
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
# Use this only on a native Linux Docker host with a real NIC on 192.168.2.0/24.
|
||||||
|
# It is not expected to work directly on macOS OrbStack because the Docker daemon
|
||||||
|
# is inside a VM and cannot attach macvlan to macOS en0.
|
||||||
|
|
||||||
|
services:
|
||||||
|
socks5:
|
||||||
|
image: serjs/go-socks5-proxy:latest
|
||||||
|
container_name: socks5-server-lan
|
||||||
|
restart: unless-stopped
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
networks:
|
||||||
|
socks5_lan:
|
||||||
|
ipv4_address: 192.168.2.200
|
||||||
|
|
||||||
|
networks:
|
||||||
|
socks5_lan:
|
||||||
|
driver: macvlan
|
||||||
|
driver_opts:
|
||||||
|
# Replace eth0 with the Linux host's physical NIC, e.g. eno1/enp3s0.
|
||||||
|
parent: eth0
|
||||||
|
ipam:
|
||||||
|
config:
|
||||||
|
- subnet: 192.168.2.0/24
|
||||||
|
gateway: 192.168.2.1
|
||||||
|
ip_range: 192.168.2.200/32
|
||||||
+12
-6
@@ -1,9 +1,15 @@
|
|||||||
version: '3'
|
|
||||||
services:
|
services:
|
||||||
|
|
||||||
socks5:
|
socks5:
|
||||||
restart: always
|
image: serjs/go-socks5-proxy:latest
|
||||||
image: serjs/go-socks5-proxy
|
container_name: socks5-server
|
||||||
env_file: .env
|
restart: unless-stopped
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
ports:
|
ports:
|
||||||
- "1080:1080"
|
- "0.0.0.0:1080:1080"
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "/socks5", "--help"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 3
|
||||||
|
start_period: 10s
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
module github.com/serjs/socks5-server
|
module github.com/serjs/socks5-server
|
||||||
|
|
||||||
go 1.23.0
|
go 1.24.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5
|
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5
|
||||||
github.com/caarlos0/env/v6 v6.10.1
|
github.com/caarlos0/env/v6 v6.10.1
|
||||||
)
|
)
|
||||||
|
|
||||||
require golang.org/x/net v0.38.0
|
require golang.org/x/net v0.46.0
|
||||||
|
|
||||||
|
replace github.com/armon/go-socks5 => github.com/serjs/go-socks5 v0.0.0-20250923183437-3920b97ee0d2
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
|
||||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
|
||||||
github.com/caarlos0/env/v6 v6.10.1 h1:t1mPSxNpei6M5yAeu1qtRdPAK29Nbcf/n3G7x+b3/II=
|
github.com/caarlos0/env/v6 v6.10.1 h1:t1mPSxNpei6M5yAeu1qtRdPAK29Nbcf/n3G7x+b3/II=
|
||||||
github.com/caarlos0/env/v6 v6.10.1/go.mod h1:hvp/ryKXKipEkcuYjs9mI4bBCg+UI0Yhgm5Zu0ddvwc=
|
github.com/caarlos0/env/v6 v6.10.1/go.mod h1:hvp/ryKXKipEkcuYjs9mI4bBCg+UI0Yhgm5Zu0ddvwc=
|
||||||
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
|
github.com/serjs/go-socks5 v0.0.0-20250923183437-3920b97ee0d2 h1:dIXY/Lrkd1rGXcN60Fc0M2x0p5/C2XcbBbtPCvVvAa4=
|
||||||
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
github.com/serjs/go-socks5 v0.0.0-20250923183437-3920b97ee0d2/go.mod h1:N2PhU16m3olAb71DduLys4mYR3oQboD4uLJmSXCSuMA=
|
||||||
|
golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4=
|
||||||
|
golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210=
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/armon/go-socks5"
|
"github.com/armon/go-socks5"
|
||||||
"github.com/caarlos0/env/v6"
|
"github.com/caarlos0/env/v6"
|
||||||
)
|
)
|
||||||
@@ -15,6 +14,8 @@ type params struct {
|
|||||||
Port string `env:"PROXY_PORT" envDefault:"1080"`
|
Port string `env:"PROXY_PORT" envDefault:"1080"`
|
||||||
AllowedDestFqdn string `env:"ALLOWED_DEST_FQDN" envDefault:""`
|
AllowedDestFqdn string `env:"ALLOWED_DEST_FQDN" envDefault:""`
|
||||||
AllowedIPs []string `env:"ALLOWED_IPS" envSeparator:"," envDefault:""`
|
AllowedIPs []string `env:"ALLOWED_IPS" envSeparator:"," envDefault:""`
|
||||||
|
ListenIP string `env:"PROXY_LISTEN_IP" envDefault:"0.0.0.0"`
|
||||||
|
RequireAuth bool `env:"REQUIRE_AUTH" envDefault:"true"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -30,12 +31,17 @@ func main() {
|
|||||||
Logger: log.New(os.Stdout, "", log.LstdFlags),
|
Logger: log.New(os.Stdout, "", log.LstdFlags),
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfg.User+cfg.Password != "" {
|
if cfg.RequireAuth {
|
||||||
|
if cfg.User == "" || cfg.Password == "" {
|
||||||
|
log.Fatalln("Error: REQUIRE_AUTH is true, but PROXY_USER and PROXY_PASSWORD are not set. The application will now exit.")
|
||||||
|
}
|
||||||
creds := socks5.StaticCredentials{
|
creds := socks5.StaticCredentials{
|
||||||
os.Getenv("PROXY_USER"): os.Getenv("PROXY_PASSWORD"),
|
cfg.User: cfg.Password,
|
||||||
}
|
}
|
||||||
cator := socks5.UserPassAuthenticator{Credentials: creds}
|
cator := socks5.UserPassAuthenticator{Credentials: creds}
|
||||||
socks5conf.AuthMethods = []socks5.Authenticator{cator}
|
socks5conf.AuthMethods = []socks5.Authenticator{cator}
|
||||||
|
} else {
|
||||||
|
log.Println("Warning: Running the proxy server without authentication. This is NOT recommended for public servers.")
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfg.AllowedDestFqdn != "" {
|
if cfg.AllowedDestFqdn != "" {
|
||||||
@@ -56,8 +62,14 @@ func main() {
|
|||||||
server.SetIPWhitelist(whitelist)
|
server.SetIPWhitelist(whitelist)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("Start listening proxy service on port %s\n", cfg.Port)
|
listenAddr := ":" + cfg.Port
|
||||||
if err := server.ListenAndServe("tcp", ":"+cfg.Port); err != nil {
|
if cfg.ListenIP != "" {
|
||||||
|
listenAddr = cfg.ListenIP + ":" + cfg.Port
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
log.Printf("Start listening proxy service on %s\n", listenAddr)
|
||||||
|
if err := server.ListenAndServe("tcp", listenAddr); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+32
@@ -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 {
|
||||||
|
|||||||
+21
-14
@@ -6,7 +6,7 @@
|
|||||||
// cancellation signals, and other request-scoped values across API boundaries
|
// cancellation signals, and other request-scoped values across API boundaries
|
||||||
// and between processes.
|
// and between processes.
|
||||||
// As of Go 1.7 this package is available in the standard library under the
|
// As of Go 1.7 this package is available in the standard library under the
|
||||||
// name [context], and migrating to it can be done automatically with [go fix].
|
// name [context].
|
||||||
//
|
//
|
||||||
// Incoming requests to a server should create a [Context], and outgoing
|
// Incoming requests to a server should create a [Context], and outgoing
|
||||||
// calls to servers should accept a Context. The chain of function
|
// calls to servers should accept a Context. The chain of function
|
||||||
@@ -38,8 +38,6 @@
|
|||||||
//
|
//
|
||||||
// See https://go.dev/blog/context for example code for a server that uses
|
// See https://go.dev/blog/context for example code for a server that uses
|
||||||
// Contexts.
|
// Contexts.
|
||||||
//
|
|
||||||
// [go fix]: https://go.dev/cmd/go#hdr-Update_packages_to_use_new_APIs
|
|
||||||
package context
|
package context
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -51,36 +49,37 @@ import (
|
|||||||
// API boundaries.
|
// API boundaries.
|
||||||
//
|
//
|
||||||
// Context's methods may be called by multiple goroutines simultaneously.
|
// Context's methods may be called by multiple goroutines simultaneously.
|
||||||
|
//
|
||||||
|
//go:fix inline
|
||||||
type Context = context.Context
|
type Context = context.Context
|
||||||
|
|
||||||
// Canceled is the error returned by [Context.Err] when the context is canceled
|
// Canceled is the error returned by [Context.Err] when the context is canceled
|
||||||
// for some reason other than its deadline passing.
|
// for some reason other than its deadline passing.
|
||||||
|
//
|
||||||
|
//go:fix inline
|
||||||
var Canceled = context.Canceled
|
var Canceled = context.Canceled
|
||||||
|
|
||||||
// DeadlineExceeded is the error returned by [Context.Err] when the context is canceled
|
// DeadlineExceeded is the error returned by [Context.Err] when the context is canceled
|
||||||
// due to its deadline passing.
|
// due to its deadline passing.
|
||||||
|
//
|
||||||
|
//go:fix inline
|
||||||
var DeadlineExceeded = context.DeadlineExceeded
|
var DeadlineExceeded = context.DeadlineExceeded
|
||||||
|
|
||||||
// Background returns a non-nil, empty Context. It is never canceled, has no
|
// Background returns a non-nil, empty Context. It is never canceled, has no
|
||||||
// values, and has no deadline. It is typically used by the main function,
|
// values, and has no deadline. It is typically used by the main function,
|
||||||
// initialization, and tests, and as the top-level Context for incoming
|
// initialization, and tests, and as the top-level Context for incoming
|
||||||
// requests.
|
// requests.
|
||||||
func Background() Context {
|
//
|
||||||
return background
|
//go:fix inline
|
||||||
}
|
func Background() Context { return context.Background() }
|
||||||
|
|
||||||
// TODO returns a non-nil, empty Context. Code should use context.TODO when
|
// TODO returns a non-nil, empty Context. Code should use context.TODO when
|
||||||
// it's unclear which Context to use or it is not yet available (because the
|
// it's unclear which Context to use or it is not yet available (because the
|
||||||
// surrounding function has not yet been extended to accept a Context
|
// surrounding function has not yet been extended to accept a Context
|
||||||
// parameter).
|
// parameter).
|
||||||
func TODO() Context {
|
//
|
||||||
return todo
|
//go:fix inline
|
||||||
}
|
func TODO() Context { return context.TODO() }
|
||||||
|
|
||||||
var (
|
|
||||||
background = context.Background()
|
|
||||||
todo = context.TODO()
|
|
||||||
)
|
|
||||||
|
|
||||||
// A CancelFunc tells an operation to abandon its work.
|
// A CancelFunc tells an operation to abandon its work.
|
||||||
// A CancelFunc does not wait for the work to stop.
|
// A CancelFunc does not wait for the work to stop.
|
||||||
@@ -95,6 +94,8 @@ type CancelFunc = context.CancelFunc
|
|||||||
//
|
//
|
||||||
// Canceling this context releases resources associated with it, so code should
|
// Canceling this context releases resources associated with it, so code should
|
||||||
// call cancel as soon as the operations running in this [Context] complete.
|
// call cancel as soon as the operations running in this [Context] complete.
|
||||||
|
//
|
||||||
|
//go:fix inline
|
||||||
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
|
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
|
||||||
return context.WithCancel(parent)
|
return context.WithCancel(parent)
|
||||||
}
|
}
|
||||||
@@ -108,6 +109,8 @@ func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
|
|||||||
//
|
//
|
||||||
// Canceling this context releases resources associated with it, so code should
|
// Canceling this context releases resources associated with it, so code should
|
||||||
// call cancel as soon as the operations running in this [Context] complete.
|
// call cancel as soon as the operations running in this [Context] complete.
|
||||||
|
//
|
||||||
|
//go:fix inline
|
||||||
func WithDeadline(parent Context, d time.Time) (Context, CancelFunc) {
|
func WithDeadline(parent Context, d time.Time) (Context, CancelFunc) {
|
||||||
return context.WithDeadline(parent, d)
|
return context.WithDeadline(parent, d)
|
||||||
}
|
}
|
||||||
@@ -122,6 +125,8 @@ func WithDeadline(parent Context, d time.Time) (Context, CancelFunc) {
|
|||||||
// defer cancel() // releases resources if slowOperation completes before timeout elapses
|
// defer cancel() // releases resources if slowOperation completes before timeout elapses
|
||||||
// return slowOperation(ctx)
|
// return slowOperation(ctx)
|
||||||
// }
|
// }
|
||||||
|
//
|
||||||
|
//go:fix inline
|
||||||
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
|
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
|
||||||
return context.WithTimeout(parent, timeout)
|
return context.WithTimeout(parent, timeout)
|
||||||
}
|
}
|
||||||
@@ -139,6 +144,8 @@ func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
|
|||||||
// interface{}, context keys often have concrete type
|
// interface{}, context keys often have concrete type
|
||||||
// struct{}. Alternatively, exported context key variables' static
|
// struct{}. Alternatively, exported context key variables' static
|
||||||
// type should be a pointer or interface.
|
// type should be a pointer or interface.
|
||||||
|
//
|
||||||
|
//go:fix inline
|
||||||
func WithValue(parent Context, key, val interface{}) Context {
|
func WithValue(parent Context, key, val interface{}) Context {
|
||||||
return context.WithValue(parent, key, val)
|
return context.WithValue(parent, key, val)
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+4
-3
@@ -1,9 +1,10 @@
|
|||||||
# github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5
|
# github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 => github.com/serjs/go-socks5 v0.0.0-20250923183437-3920b97ee0d2
|
||||||
## explicit
|
## explicit
|
||||||
github.com/armon/go-socks5
|
github.com/armon/go-socks5
|
||||||
# github.com/caarlos0/env/v6 v6.10.1
|
# github.com/caarlos0/env/v6 v6.10.1
|
||||||
## explicit; go 1.17
|
## explicit; go 1.17
|
||||||
github.com/caarlos0/env/v6
|
github.com/caarlos0/env/v6
|
||||||
# golang.org/x/net v0.38.0
|
# golang.org/x/net v0.46.0
|
||||||
## explicit; go 1.23.0
|
## explicit; go 1.24.0
|
||||||
golang.org/x/net/context
|
golang.org/x/net/context
|
||||||
|
# github.com/armon/go-socks5 => github.com/serjs/go-socks5 v0.0.0-20250923183437-3920b97ee0d2
|
||||||
|
|||||||
Reference in New Issue
Block a user