Skip to content

Commit fef2c69

Browse files
authored
Add tunnelling HTTP requests to a Socks5 Proxy (#10)
1 parent 12fa609 commit fef2c69

File tree

5 files changed

+47
-5
lines changed

5 files changed

+47
-5
lines changed

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Code based on the guide here: <https://medium.com/@mlowicki/http-s-proxy-in-gola
1818
- Can log request headers.
1919
- Can log failed authentication attempt details.
2020
- Printing version number.
21+
- Tunnel HTTP proxy to socks5 proxy
2122

2223
## Install
2324

@@ -48,6 +49,10 @@ You can run the binary directly:
4849

4950
```bash
5051
./simple-proxy
52+
53+
# tunnel the http proxy to socks5 proxy
54+
# client -> localhost:7990 [http proxy] -> 127.0.0.1:7890 [socks5 proxy] -> server
55+
./simple-proxy -port 7990 -socks 127.0.0.1:7890
5156
```
5257

5358
## Windows
@@ -86,6 +91,8 @@ Usage of simple-proxy:
8691
log to standard error instead of files
8792
-port string
8893
proxy port to listen on (default "8888")
94+
-socks5 string
95+
proxy tunnel the http requests to a socks5 proxy (default "", feature off)
8996
-protocol string
9097
proxy protocol (http or https) (default "http")
9198
-stderrthreshold value

go.mod

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,7 @@ module github.com/jthomperoo/simple-proxy
22

33
go 1.22
44

5-
require github.com/golang/glog v1.0.0
5+
require (
6+
github.com/golang/glog v1.0.0
7+
golang.org/x/net v0.30.0
8+
)

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ=
22
github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4=
3+
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
4+
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=

main.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
"time"
1212

1313
"github.com/golang/glog"
14-
"github.com/jthomperoo/simple-proxy/proxy"
14+
my_proxy "github.com/jthomperoo/simple-proxy/proxy"
1515
)
1616

1717
var (
@@ -36,6 +36,8 @@ func main() {
3636
flag.StringVar(&bind, "bind", "0.0.0.0", "address to bind the proxy server to")
3737
var port string
3838
flag.StringVar(&port, "port", "8888", "proxy port to listen on")
39+
var socks5 string
40+
flag.StringVar(&socks5, "socks5", "", "SOCKS5 proxy for tunneling")
3941
var certPath string
4042
flag.StringVar(&certPath, "cert", "", "path to cert file")
4143
var keyPath string
@@ -63,9 +65,11 @@ func main() {
6365
glog.Fatalf("If using HTTPS protocol --cert and --key are required\n")
6466
}
6567

68+
my_proxy.Socks5 = socks5
69+
6670
var handler http.Handler
6771
if basicAuth == "" {
68-
handler = &proxy.ProxyHandler{
72+
handler = &my_proxy.ProxyHandler{
6973
Timeout: time.Duration(timeoutSecs) * time.Second,
7074
LogAuth: logAuth,
7175
LogHeaders: logHeaders,
@@ -75,7 +79,7 @@ func main() {
7579
if len(parts) < 2 {
7680
glog.Fatalf("Invalid basic auth provided, must be in format 'username:password', auth: %s\n", basicAuth)
7781
}
78-
handler = &proxy.ProxyHandler{
82+
handler = &my_proxy.ProxyHandler{
7983
Timeout: time.Duration(timeoutSecs) * time.Second,
8084
Username: &parts[0],
8185
Password: &parts[1],
@@ -93,6 +97,9 @@ func main() {
9397

9498
if protocol == httpProtocol {
9599
glog.V(0).Infoln("Starting HTTP proxy...")
100+
if socks5 != "" {
101+
glog.V(0).Infof("Tunneling HTTP requests to SOCKS5 proxy: %s\n", socks5)
102+
}
96103
log.Fatal(server.ListenAndServe())
97104
} else {
98105
glog.V(0).Infoln("Starting HTTPS proxy...")

proxy/proxy.go

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,12 @@ import (
99
"time"
1010

1111
"github.com/golang/glog"
12+
net_proxy "golang.org/x/net/proxy"
1213
)
1314

15+
// Using a socks5 proxy to tunnel the HTTP requests, e.g., 127.0.0.1:7890
16+
var Socks5 = ""
17+
1418
func NewProxyHandler(timeoutSeconds int) *ProxyHandler {
1519
return &ProxyHandler{
1620
Timeout: time.Duration(timeoutSeconds) * time.Second,
@@ -55,7 +59,26 @@ func (p *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
5559
}
5660

5761
func handleTunneling(w http.ResponseWriter, r *http.Request, timeout time.Duration) {
58-
dest_conn, err := net.DialTimeout("tcp", r.Host, timeout)
62+
var dest_conn net.Conn
63+
var err error
64+
65+
// Check if the socks5 proxy is set
66+
// Then tunnel to socks5 proxy
67+
if Socks5 == "" {
68+
dest_conn, err = net.DialTimeout("tcp", r.Host, timeout)
69+
} else {
70+
var socks5_dailer net_proxy.Dialer
71+
socks5_dailer, err = net_proxy.SOCKS5("tcp", Socks5, nil, &net.Dialer{
72+
Timeout: timeout,
73+
KeepAlive: 30 * time.Second,
74+
})
75+
if err != nil {
76+
glog.Errorf("Failed to dail socks5 proxy %s, %s\n", Socks5, err.Error())
77+
http.Error(w, err.Error(), http.StatusServiceUnavailable)
78+
return
79+
}
80+
dest_conn, err = socks5_dailer.Dial("tcp", r.Host)
81+
}
5982
if err != nil {
6083
glog.Errorf("Failed to dial host, %s\n", err.Error())
6184
http.Error(w, err.Error(), http.StatusServiceUnavailable)

0 commit comments

Comments
 (0)