2015-11-21 01:59:49 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto/tls"
|
|
|
|
"net"
|
|
|
|
"net/http"
|
|
|
|
"net/http/httptest"
|
|
|
|
"os/exec"
|
|
|
|
"time"
|
|
|
|
|
2016-04-02 10:40:21 +00:00
|
|
|
"github.com/go-check/check"
|
|
|
|
|
2015-11-21 01:59:49 +00:00
|
|
|
checker "github.com/vdemeester/shakers"
|
|
|
|
)
|
|
|
|
|
|
|
|
// HTTPSSuite
|
|
|
|
type HTTPSSuite struct{ BaseSuite }
|
|
|
|
|
|
|
|
// TestWithSNIConfigHandshake involves a client sending a SNI hostname of
|
|
|
|
// "snitest.com", which happens to match the CN of 'snitest.com.crt'. The test
|
|
|
|
// verifies that traefik presents the correct certificate.
|
|
|
|
func (s *HTTPSSuite) TestWithSNIConfigHandshake(c *check.C) {
|
2016-01-13 21:46:44 +00:00
|
|
|
cmd := exec.Command(traefikBinary, "--configFile=fixtures/https/https_sni.toml")
|
2015-11-21 01:59:49 +00:00
|
|
|
err := cmd.Start()
|
|
|
|
c.Assert(err, checker.IsNil)
|
|
|
|
defer cmd.Process.Kill()
|
|
|
|
|
|
|
|
time.Sleep(500 * time.Millisecond)
|
|
|
|
|
|
|
|
tlsConfig := &tls.Config{
|
|
|
|
InsecureSkipVerify: true,
|
|
|
|
ServerName: "snitest.com",
|
|
|
|
}
|
2016-01-13 21:46:44 +00:00
|
|
|
conn, err := tls.Dial("tcp", "127.0.0.1:4443", tlsConfig)
|
2015-11-21 01:59:49 +00:00
|
|
|
c.Assert(err, checker.IsNil, check.Commentf("failed to connect to server"))
|
|
|
|
|
|
|
|
defer conn.Close()
|
|
|
|
err = conn.Handshake()
|
|
|
|
c.Assert(err, checker.IsNil, check.Commentf("TLS handshake error"))
|
|
|
|
|
|
|
|
cs := conn.ConnectionState()
|
|
|
|
err = cs.PeerCertificates[0].VerifyHostname("snitest.com")
|
|
|
|
c.Assert(err, checker.IsNil, check.Commentf("certificate did not match SNI servername"))
|
|
|
|
}
|
|
|
|
|
|
|
|
// TestWithSNIConfigRoute involves a client sending HTTPS requests with
|
|
|
|
// SNI hostnames of "snitest.org" and "snitest.com". The test verifies
|
|
|
|
// that traefik routes the requests to the expected backends.
|
|
|
|
func (s *HTTPSSuite) TestWithSNIConfigRoute(c *check.C) {
|
2016-01-13 21:46:44 +00:00
|
|
|
cmd := exec.Command(traefikBinary, "--configFile=fixtures/https/https_sni.toml")
|
2015-11-21 01:59:49 +00:00
|
|
|
err := cmd.Start()
|
|
|
|
c.Assert(err, checker.IsNil)
|
|
|
|
defer cmd.Process.Kill()
|
|
|
|
|
|
|
|
backend1 := startTestServer("9010", 204)
|
|
|
|
backend2 := startTestServer("9020", 205)
|
|
|
|
defer backend1.Close()
|
|
|
|
defer backend2.Close()
|
|
|
|
|
|
|
|
time.Sleep(2000 * time.Millisecond)
|
|
|
|
|
|
|
|
tr1 := &http.Transport{
|
|
|
|
TLSClientConfig: &tls.Config{
|
|
|
|
InsecureSkipVerify: true,
|
|
|
|
ServerName: "snitest.com",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
tr2 := &http.Transport{
|
|
|
|
TLSClientConfig: &tls.Config{
|
|
|
|
InsecureSkipVerify: true,
|
|
|
|
ServerName: "snitest.org",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
client := &http.Client{Transport: tr1}
|
2016-01-13 21:46:44 +00:00
|
|
|
req, _ := http.NewRequest("GET", "https://127.0.0.1:4443/", nil)
|
2015-11-21 01:59:49 +00:00
|
|
|
req.Host = "snitest.com"
|
|
|
|
req.Header.Set("Host", "snitest.com")
|
|
|
|
req.Header.Set("Accept", "*/*")
|
|
|
|
resp, err := client.Do(req)
|
|
|
|
c.Assert(err, checker.IsNil)
|
|
|
|
// Expected a 204 (from backend1)
|
|
|
|
c.Assert(resp.StatusCode, checker.Equals, 204)
|
|
|
|
|
|
|
|
client = &http.Client{Transport: tr2}
|
2016-01-13 21:46:44 +00:00
|
|
|
req, _ = http.NewRequest("GET", "https://127.0.0.1:4443/", nil)
|
2015-11-21 01:59:49 +00:00
|
|
|
req.Host = "snitest.org"
|
|
|
|
req.Header.Set("Host", "snitest.org")
|
|
|
|
req.Header.Set("Accept", "*/*")
|
|
|
|
resp, err = client.Do(req)
|
|
|
|
c.Assert(err, checker.IsNil)
|
|
|
|
// Expected a 205 (from backend2)
|
|
|
|
c.Assert(resp.StatusCode, checker.Equals, 205)
|
|
|
|
}
|
|
|
|
|
|
|
|
func startTestServer(port string, statusCode int) (ts *httptest.Server) {
|
|
|
|
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
w.WriteHeader(statusCode)
|
|
|
|
})
|
|
|
|
listener, err := net.Listen("tcp", "127.0.0.1:"+port)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
ts = &httptest.Server{
|
|
|
|
Listener: listener,
|
|
|
|
Config: &http.Server{Handler: handler},
|
|
|
|
}
|
|
|
|
ts.Start()
|
|
|
|
return
|
|
|
|
}
|