Skip to content

Commit

Permalink
proxy: add validaing https support
Browse files Browse the repository at this point in the history
check README.md as the URL parameters have changed
  • Loading branch information
hoffie committed Jul 25, 2023
1 parent 5ae89a6 commit ee694ee
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 31 deletions.
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@ You will need to configure your software to use sshified as an HTTP proxy.
A popular use case is using the monitoring tool [Prometheus](https://prometheus.io).
By pointing Prometheus to sshified, all traffic will be tunneled over SSH and can therefore be run over untrusted networks.

### Non-features
Currently, no HTTPS (or general CONNECT) support is implemented or planned.
Rudimentary non-validating HTTPS client support exists by using the special `?__sshified_use_insecure_https=1` query parameter.
Rudimentary HTTPS client support exists by using the special `?__sshified_use_https=1` parameter.
If certificate validation against the system trust store should be disabled, use `&__sshified_https_insecure_skip_verify=1` as an additional query parameter.

## Status
This project is considered feature-complete.
Expand Down
41 changes: 26 additions & 15 deletions proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func NewProxyHandler(ssh *sshTransport) *proxyHandler {
}

func (ph *proxyHandler) ServeHTTP(rw http.ResponseWriter, origReq *http.Request) {
proxyReq := NewProxyRequest(rw, origReq, ph.ssh.Transport)
proxyReq := NewProxyRequest(rw, origReq, ph.ssh.TransportRegular, ph.ssh.TransportTLSSkipVerify)
err := proxyReq.Handle()
if err != nil {
log.WithFields(log.Fields{
Expand All @@ -33,20 +33,23 @@ func (ph *proxyHandler) ServeHTTP(rw http.ResponseWriter, origReq *http.Request)
}

type proxyRequest struct {
rw http.ResponseWriter
origReq *http.Request
transport http.RoundTripper
requestedURL string
upstreamClient *http.Client
upstreamResponse *http.Response
upstreamRequest *http.Request
rw http.ResponseWriter
origReq *http.Request
transportRegular http.RoundTripper
transportTLSSkipVerify http.RoundTripper
requestedURL string
upstreamClient *http.Client
upstreamResponse *http.Response
upstreamRequest *http.Request
httpsInsecureSkipVerify bool
}

func NewProxyRequest(rw http.ResponseWriter, origReq *http.Request, transport http.RoundTripper) *proxyRequest {
func NewProxyRequest(rw http.ResponseWriter, origReq *http.Request, transportRegular, transportTLSSkipVerify http.RoundTripper) *proxyRequest {
return &proxyRequest{
rw: rw,
origReq: origReq,
transport: transport,
rw: rw,
origReq: origReq,
transportRegular: transportRegular,
transportTLSSkipVerify: transportTLSSkipVerify,
}
}

Expand Down Expand Up @@ -79,13 +82,15 @@ func (pr *proxyRequest) Handle() error {
}

func (pr *proxyRequest) buildURL() {
https := pr.origReq.URL.Query().Get("__sshified_use_insecure_https")
https := pr.origReq.URL.Query().Get("__sshified_use_https")
if https == "" {
pr.origReq.URL.Scheme = "http"
} else {
// TLSClientConfig is hardcoded and re-used in sshtransport.go
pr.origReq.URL.Scheme = "https"
values := pr.origReq.URL.Query()
if values.Get("__sshified_https_insecure_skip_verify") == "1" {
pr.httpsInsecureSkipVerify = true
}
for k := range values {
if strings.HasPrefix(k, "__sshified_") {
values.Del(k)
Expand Down Expand Up @@ -119,8 +124,14 @@ func (pr *proxyRequest) buildRequest() error {
}
}
pr.upstreamRequest.Body = pr.origReq.Body
var transport http.RoundTripper
if pr.httpsInsecureSkipVerify {
transport = pr.transportTLSSkipVerify
} else {
transport = pr.transportRegular
}
pr.upstreamClient = &http.Client{
Transport: pr.transport,
Transport: transport,
Timeout: time.Duration(*timeout) * time.Second,
}
return nil
Expand Down
30 changes: 17 additions & 13 deletions sshtransport.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,16 @@ func makePubkeyAuth(keyFile string) ([]ssh.AuthMethod, error) {
}

type sshTransport struct {
port int
user string
auth []ssh.AuthMethod
sshClientPool *sshClientPool
Transport http.RoundTripper
keyFile string
knownHostsFile string
knownHostsCallback ssh.HostKeyCallback
nextProxyAddr string
port int
user string
auth []ssh.AuthMethod
sshClientPool *sshClientPool
TransportRegular http.RoundTripper
TransportTLSSkipVerify http.RoundTripper
keyFile string
knownHostsFile string
knownHostsCallback ssh.HostKeyCallback
nextProxyAddr string
}

func NewSSHTransport(user, keyFile, knownHostsFile string, port int, nextProxyAddr string) (*sshTransport, error) {
Expand All @@ -53,7 +54,7 @@ func NewSSHTransport(user, keyFile, knownHostsFile string, port int, nextProxyAd
if err != nil {
return nil, err
}
t.createTransport()
t.createTransports()
return t, nil
}

Expand All @@ -71,17 +72,20 @@ func (t *sshTransport) LoadFiles() error {
return nil
}

func (t *sshTransport) createTransport() {
t.Transport = &http.Transport{
func (t *sshTransport) createTransports() {
transportRegular := &http.Transport{
Proxy: nil,
Dial: t.dial,
// FIXME: DialContext
MaxIdleConns: 100,
IdleConnTimeout: time.Duration(*timeout) * 2 * time.Second,
ResponseHeaderTimeout: time.Duration(*timeout) * time.Second,
ExpectContinueTimeout: 1 * time.Second,
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
transportTLSSkipVerify := transportRegular.Clone()
transportTLSSkipVerify.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
t.TransportRegular = transportRegular
t.TransportTLSSkipVerify = transportTLSSkipVerify
}

func (t *sshTransport) checkHostKey(hostname string, remote net.Addr, key ssh.PublicKey) error {
Expand Down

0 comments on commit ee694ee

Please sign in to comment.