diff --git a/README.md b/README.md index e31f3d9..1555bb7 100644 --- a/README.md +++ b/README.md @@ -29,10 +29,39 @@ gohpts -s :1080 -l :8080 Specify http server in proxy configuration of Postman +## Features + +- **DNS Leak Protection** + DNS resolution occurs on SOCKS5 server side. + +- **CONNECT Method Support** + Supports HTTP CONNECT tunneling, enabling HTTPS and other TCP-based protocols. + +- **Trailer Headers Support** + Handles HTTP trailer headers + +- **Chunked Transfer Encoding** + Handles chunked and streaming responses + +- **SOCKS5 Authentication Support** + Supports username/password authentication for SOCKS5 proxies. + +- **Lightweight and Fast** + Designed with minimal overhead and efficient request handling. + +- **Cross-Platform** + Compatible with all major operating systems. + ## Installation You can download the binary for your platform from [Releases](https://github.com/shadowy-pycoder/go-http-proxy-to-socks/releases) page. +Example: + +```shell +HPTS_RELEASE=v1.3.4; wget -v https://github.com/shadowy-pycoder/go-http-proxy-to-socks/releases/download/$HPTS_RELEASE/gohpts-$HPTS_RELEASE-linux-amd64.tar.gz -O gohpts && tar xvzf gohpts && mv -f gohpts-$HPTS_RELEASE-linux-amd64 gohpts && gohpts -h +``` + Alternatively, you can install it using `go install` command (requires Go [1.24](https://go.dev/doc/install) or later): ```shell @@ -68,8 +97,12 @@ GitHub: https://github.com/shadowy-pycoder/go-http-proxy-to-socks Usage: gohpts [OPTIONS] Options: -h Show this help message and exit. + -c string + Path to certificate PEM encoded file -d Show logs in DEBUG mode -j Show logs in JSON format + -k string + Path to private key PEM encoded file -l value Address of HTTP proxy server (Default: localhost:8080) -p Password for SOCKS5 proxy (not echoed to terminal) @@ -101,6 +134,12 @@ gohpts -s 1080 -l 8080 -d -j -u user -p SOCKS5 Password: #you will be prompted for password input here ``` +Run http proxy over TLS connection + +```shell +gohpts -s 1080 -l 8080 -c "path/to/certificate" -k "path/to/private/key" +``` + ## License MIT diff --git a/cmd/gohpts/cli.go b/cmd/gohpts/cli.go index c3a01db..40a99b6 100644 --- a/cmd/gohpts/cli.go +++ b/cmd/gohpts/cli.go @@ -63,6 +63,8 @@ func root(args []string) error { } return nil }) + flags.StringVar(&conf.CertFile, "c", "", "Path to certificate PEM encoded file ") + flags.StringVar(&conf.KeyFile, "k", "", "Path to private key PEM encoded file ") flags.BoolFunc("d", "Show logs in DEBUG mode", func(flagValue string) error { conf.Debug = true return nil diff --git a/gohpts.go b/gohpts.go index 7b2108b..d0b88e0 100644 --- a/gohpts.go +++ b/gohpts.go @@ -90,6 +90,8 @@ type proxyApp struct { httpClient *http.Client sockDialer proxy.Dialer logger *zerolog.Logger + certFile string + keyFile string } func (p *proxyApp) doReq(w http.ResponseWriter, r *http.Request, socks bool) *http.Response { @@ -312,8 +314,14 @@ func (p *proxyApp) handler() http.HandlerFunc { func (p *proxyApp) Run() { p.httpServer.Handler = p.handler() - if err := p.httpServer.ListenAndServe(); err != nil { - p.logger.Fatal().Err(err).Msg("Unable to start HTTP server") + if p.certFile != "" && p.keyFile != "" { + if err := p.httpServer.ListenAndServeTLS(p.certFile, p.keyFile); err != nil { + p.logger.Fatal().Err(err).Msg("Unable to start HTTPS server") + } + } else { + if err := p.httpServer.ListenAndServe(); err != nil { + p.logger.Fatal().Err(err).Msg("Unable to start HTTP server") + } } } @@ -324,6 +332,8 @@ type Config struct { Json bool User string Pass string + CertFile string + KeyFile string } func New(conf *Config) *proxyApp { @@ -364,6 +374,16 @@ func New(conf *Config) *proxyApp { WriteTimeout: writeTimeout, MaxHeaderBytes: 1 << 20, Protocols: new(http.Protocols), + TLSConfig: &tls.Config{ + MinVersion: tls.VersionTLS12, + CurvePreferences: []tls.CurveID{tls.CurveP521, tls.CurveP384, tls.CurveP256}, + CipherSuites: []uint16{ + tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, + tls.TLS_RSA_WITH_AES_256_GCM_SHA384, + tls.TLS_RSA_WITH_AES_256_CBC_SHA, + }, + }, } hs.TLSNextProto = make(map[string]func(*http.Server, *tls.Conn, http.Handler)) hs.Protocols.SetHTTP1(true) @@ -376,6 +396,18 @@ func New(conf *Config) *proxyApp { }, } logger.Info().Msgf("SOCKS5 Proxy: %s", conf.AddrSOCKS) - logger.Info().Msgf("HTTP Proxy: %s", conf.AddrHTTP) - return &proxyApp{httpServer: hs, sockClient: socks, httpClient: hc, sockDialer: dialer, logger: &logger} + if conf.CertFile != "" && conf.KeyFile != "" { + logger.Info().Msgf("HTTPS Proxy: %s", conf.AddrHTTP) + } else { + logger.Info().Msgf("HTTP Proxy: %s", conf.AddrHTTP) + } + return &proxyApp{ + httpServer: hs, + sockClient: socks, + httpClient: hc, + sockDialer: dialer, + logger: &logger, + certFile: conf.CertFile, + keyFile: conf.KeyFile, + } } diff --git a/version.go b/version.go index b2f385a..e6ebbfc 100644 --- a/version.go +++ b/version.go @@ -1,3 +1,3 @@ package gohpts -const Version string = "gohpts v1.3.4" +const Version string = "gohpts v1.4.0"