Skip to content

Commit

Permalink
support http proxy
Browse files Browse the repository at this point in the history
  • Loading branch information
ysmood committed May 15, 2024
1 parent 9cf8d6f commit 7a0d015
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 2 deletions.
2 changes: 2 additions & 0 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
"copyloopvar",
"creack",
"dehub",
"elazarl",
"errchkjson",
"forbidigo",
"funlen",
"Getsize",
"gobwas",
"golangci",
"gomnd",
"goproxy",
"goreleaser",
"hubdb",
"jawher",
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ require (
)

require (
github.com/elazarl/goproxy v0.0.0-20231117061959-7cc037d33fb5
github.com/go-git/go-billy/v5 v5.5.0
github.com/gobwas/ws v1.4.0
github.com/jawher/mow.cli v1.2.0
Expand Down
5 changes: 5 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxG
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/elazarl/goproxy v0.0.0-20231117061959-7cc037d33fb5 h1:m62nsMU279qRD9PQSWD1l66kmkXzuYcnVJqL4XLeV2M=
github.com/elazarl/goproxy v0.0.0-20231117061959-7cc037d33fb5/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2 h1:dWB6v3RcOy03t/bUadywsbyrQwCqZeNIEX6M1OtSZOM=
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU=
github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow=
github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
Expand Down Expand Up @@ -43,6 +47,7 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rasky/go-xdr v0.0.0-20170124162913-1a41d1a06c93 h1:UVArwN/wkKjMVhh2EQGC0tEc1+FqiLlvYXY5mQ2f8Wg=
github.com/rasky/go-xdr v0.0.0-20170124162913-1a41d1a06c93/go.mod h1:Nfe4efndBz4TibWycNE+lqyJZiMX4ycx+QKV8Ta0f/o=
github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
Expand Down
36 changes: 36 additions & 0 deletions lib/hub_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ package dehub_test
import (
"bytes"
"context"
"fmt"
"net"
"net/http"
"net/url"
"testing"
"time"

Expand Down Expand Up @@ -66,6 +68,40 @@ func TestSocks5(t *testing.T) {
g.Has(res, "Example Domain")
}

func TestHTTPProxy(t *testing.T) {
g := got.T(t)

hubAddr := startHub(g, nil)

servantConn, err := net.Dial("tcp", hubAddr)
g.E(err)
servant := dehub.NewServant("test", prvKey(g), pubKey(g))
go servant.Serve(servantConn)()

masterConn, err := net.Dial("tcp", hubAddr)
g.E(err)
master := dehub.NewMaster("test", prvKey(g), pubKey(g))
g.E(master.Connect(masterConn))

proxyServer, err := net.Listen("tcp", ":0")
g.E(err)

go func() { g.E(master.ForwardHTTP(proxyServer)) }()

proxyUrl, err := url.Parse(fmt.Sprintf("http://127.0.0.1:%d", proxyServer.Addr().(*net.TCPAddr).Port))
g.E(err)

req, err := http.NewRequestWithContext(g.Context(), "", "http://example.com", nil)
g.E(err)

c := http.Client{Transport: &http.Transport{Proxy: http.ProxyURL(proxyUrl)}}
res, err := c.Do(req)
g.E(err)
defer func() { g.E(res.Body.Close()) }()

g.Has(g.Read(res.Body).String(), "Example Domain")
}

func reqViaProxy(g got.G, proxyHost string, u string) string {
dialer, err := proxy.SOCKS5("tcp", proxyHost, nil, proxy.Direct)
g.E(err)
Expand Down
39 changes: 38 additions & 1 deletion lib/master.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
package dehub

import (
"context"
"encoding/json"
"errors"
"fmt"
"io"
"log/slog"
"net"
"net/http"
"os"

"github.com/creack/pty"
"github.com/elazarl/goproxy"
"github.com/hashicorp/yamux"
"golang.org/x/crypto/ssh"
"golang.org/x/crypto/ssh/agent"
"golang.org/x/net/proxy"
"golang.org/x/term"
)

Expand Down Expand Up @@ -143,7 +147,7 @@ func (m *Master) ForwardSocks5(listenTo net.Listener) error {
return nil
}

return fmt.Errorf("failed to accept sock5 connection: %w", err)
return fmt.Errorf("failed to accept socks5 connection: %w", err)
}

m.Logger.Info("new socks5 connection")
Expand Down Expand Up @@ -176,6 +180,29 @@ func (m *Master) ForwardSocks5(listenTo net.Listener) error {
}
}

func (m *Master) ForwardHTTP(listenTo net.Listener) error {
ch, _, err := m.sshConn.OpenChannel(CommandForwardSocks5.String(), nil)
if err != nil {
return fmt.Errorf("failed to open http proxy channel: %w", err)
}

defer func() { _ = ch.Close() }()

tunnel, err := yamux.Client(ch, nil)
if err != nil {
return fmt.Errorf("failed to create http proxy yamux tunnel: %w", err)
}

dialer, _ := proxy.SOCKS5("tcp", "", nil, &tunnelDialer{tunnel})

httpProxy := goproxy.NewProxyHttpServer()
httpProxy.Tr.DialContext = func(_ context.Context, network, addr string) (net.Conn, error) {
return dialer.Dial(network, addr)
}

return http.Serve(listenTo, httpProxy)
}

func (m *Master) ServeNFS(remoteDir string, fsSrv net.Listener, cacheLimit int) error {
if cacheLimit <= 0 {
cacheLimit = 2048
Expand Down Expand Up @@ -243,3 +270,13 @@ func (m *Master) serveNFS(tunnel *yamux.Session, fServer net.Listener) {
}
}()
}

type tunnelDialer struct {
tunnel interface {
Open() (net.Conn, error)
}
}

func (d *tunnelDialer) Dial(network, address string) (net.Conn, error) {
return d.tunnel.Open()
}
16 changes: 15 additions & 1 deletion master.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ type masterConf struct {

outputFile string

socks5 string
socks5 string
httpProxy string

nfsAddr string
remoteDir string
Expand Down Expand Up @@ -51,6 +52,7 @@ func setupMasterCLI(app *cli.Cli) {
c.StringOptPtr(&conf.outputFile, "o output", "tmp/dehub-master.log", "The file path to append the output.")

c.StringOptPtr(&conf.socks5, "s socks5", "", "The address of the socks5 server.")
c.StringOptPtr(&conf.httpProxy, "x http-proxy", "", "The address of the http proxy server.")

c.StringOptPtr(&conf.nfsAddr, "n nfs-addr", "", "The address of the nfs server.")
c.StringOptPtr(&conf.remoteDir, "r remote-dir", ".", "The remote directory to serve.")
Expand Down Expand Up @@ -92,6 +94,18 @@ func runMaster(conf masterConf) { //nolint: funlen
wait = true
}

// Forward http
if conf.httpProxy != "" {
l, err := net.Listen("tcp", conf.httpProxy)
e(err)

master.Logger.Info("http proxy server on", "addr", l.Addr().String())

go func() { e(master.ForwardHTTP(l)) }()

wait = true
}

// Forward dir
if conf.nfsAddr != "" {
fsSrv, err := net.Listen("tcp", conf.nfsAddr)
Expand Down

0 comments on commit 7a0d015

Please sign in to comment.