Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

setting sni to match host #896

Merged
merged 1 commit into from
Jul 18, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 5 additions & 15 deletions main.go
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@ import (
"crypto/tls"
"encoding/json"
"fmt"
"github.com/fabiolb/fabio/transport"
gkm "github.com/go-kit/kit/metrics"
"io"
"log"
@@ -68,6 +69,8 @@ func main() {
return
}

transport.SetConfig(cfg)

log.Printf("[INFO] Setting log level to %s", logOutput.Level())
if !logOutput.SetLevel(cfg.Log.Level) {
log.Printf("[INFO] Cannot set log level to %s", cfg.Log.Level)
@@ -208,19 +211,6 @@ func newHTTPProxy(cfg *config.Config, statsHandler *proxy.HttpStatsHandler) *pro
log.Printf("[INFO] Using routing strategy %q", cfg.Proxy.Strategy)
log.Printf("[INFO] Using route matching %q", cfg.Proxy.Matcher)

newTransport := func(tlscfg *tls.Config) *http.Transport {
return &http.Transport{
ResponseHeaderTimeout: cfg.Proxy.ResponseHeaderTimeout,
IdleConnTimeout: cfg.Proxy.IdleConnTimeout,
MaxIdleConnsPerHost: cfg.Proxy.MaxConn,
Dial: (&net.Dialer{
Timeout: cfg.Proxy.DialTimeout,
KeepAlive: cfg.Proxy.KeepAliveTimeout,
}).Dial,
TLSClientConfig: tlscfg,
}
}

authSchemes, err := auth.LoadAuthSchemes(cfg.Proxy.AuthSchemes)

if err != nil {
@@ -229,8 +219,8 @@ func newHTTPProxy(cfg *config.Config, statsHandler *proxy.HttpStatsHandler) *pro

return &proxy.HTTPProxy{
Config: cfg.Proxy,
Transport: newTransport(nil),
InsecureTransport: newTransport(&tls.Config{InsecureSkipVerify: true}),
Transport: transport.NewTransport(nil),
InsecureTransport: transport.NewTransport(&tls.Config{InsecureSkipVerify: true}),
Lookup: func(r *http.Request) *route.Target {
t := route.GetTable().Lookup(r, r.Header.Get("trace"), pick, match, globCache, cfg.GlobMatchingDisabled)
if t == nil {
42 changes: 42 additions & 0 deletions proxy/http_integration_test.go
Original file line number Diff line number Diff line change
@@ -529,6 +529,48 @@ func TestProxyHTTPSUpstream(t *testing.T) {
}
}

type sniHandler struct {
sni string
}

func (s *sniHandler) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
if request.TLS != nil {
s.sni = request.TLS.ServerName
}
writer.Write([]byte(`OK`))
}

func TestProxyHTTPSTransport(t *testing.T) {
sni := &sniHandler{}

server := httptest.NewUnstartedServer(sni)
server.TLS = tlsServerConfig()
server.StartTLS()
defer server.Close()

proxy := httptest.NewServer(&HTTPProxy{
Config: config.Proxy{},
Transport: &http.Transport{TLSClientConfig: tlsClientConfig()},
Lookup: func(r *http.Request) *route.Target {
tbl, _ := route.NewTable(bytes.NewBufferString("route add srv / " + server.URL + ` opts "proto=https host=foo.com tlsskipverify=true"`))
return tbl.Lookup(r, "", route.Picker["rr"], route.Matcher["prefix"], globCache, globEnabled)
},
})
defer proxy.Close()

resp, body := mustGet(proxy.URL)
if got, want := resp.StatusCode, http.StatusOK; got != want {
t.Fatalf("got status %d want %d", got, want)
}
if got, want := string(body), "OK"; got != want {
t.Fatalf("got body %q want %q", got, want)
}
if got, want := sni.sni, "foo.com"; got != want {
t.Fatalf("got sni %q want %q", got, want)
}

}

func TestProxyHTTPSUpstreamSkipVerify(t *testing.T) {
server := httptest.NewUnstartedServer(okHandler)
server.TLS = &tls.Config{}
6 changes: 4 additions & 2 deletions proxy/http_proxy.go
Original file line number Diff line number Diff line change
@@ -193,9 +193,11 @@ func (p *HTTPProxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
trace.InjectHeaders(span, r)

upgrade, accept := r.Header.Get("Upgrade"), r.Header.Get("Accept")

tr := p.Transport
if t.TLSSkipVerify {
if t.Transport != nil {
tr = t.Transport
} else if t.TLSSkipVerify {
tr = p.InsecureTransport
}

7 changes: 7 additions & 0 deletions route/route.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package route

import (
"crypto/tls"
"fmt"
"github.com/fabiolb/fabio/transport"
"log"
"net/url"
"reflect"
@@ -66,12 +68,17 @@ func (r *Route) addTarget(service string, targetURL *url.URL, fixedWeight float6

var err error
if opts != nil {

t.StripPath = opts["strip"]
t.PrependPath = opts["prepend"]
t.TLSSkipVerify = opts["tlsskipverify"] == "true"
t.Host = opts["host"]
t.ProxyProto = opts["pxyproto"] == "true"

if t.Host != "" && (t.URL.Scheme == "https" || opts["proto"] == "https") {
t.Transport = transport.NewTransport(&tls.Config{ServerName: t.Host, InsecureSkipVerify: t.TLSSkipVerify})
}

if opts["redirect"] != "" {
t.RedirectCode, err = strconv.Atoi(opts["redirect"])
if err != nil {
4 changes: 4 additions & 0 deletions route/target.go
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ package route

import (
gkm "github.com/go-kit/kit/metrics"
"net/http"
"net/url"
"strings"
)
@@ -67,6 +68,9 @@ type Target struct {

// ProxyProto enables PROXY Protocol on upstream connection
ProxyProto bool

// Transport allows for different types of transports
Transport *http.Transport
}

func (t *Target) BuildRedirectURL(requestURL *url.URL) {
29 changes: 29 additions & 0 deletions transport/transport.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package transport

import (
"crypto/tls"
"github.com/fabiolb/fabio/config"
"net"
"net/http"
)

var (
cfg *config.Config = &config.Config{}
)

func NewTransport(tlscfg *tls.Config) *http.Transport {
return &http.Transport{
ResponseHeaderTimeout: cfg.Proxy.ResponseHeaderTimeout,
IdleConnTimeout: cfg.Proxy.IdleConnTimeout,
MaxIdleConnsPerHost: cfg.Proxy.MaxConn,
Dial: (&net.Dialer{
Timeout: cfg.Proxy.DialTimeout,
KeepAlive: cfg.Proxy.KeepAliveTimeout,
}).Dial,
TLSClientConfig: tlscfg,
}
}

func SetConfig(cfg *config.Config) {
cfg = cfg
}