mirror of https://github.com/fatedier/frp
Added optional HTTPS client certificate authentication to https2http and https2https
parent
773169e0c4
commit
acb53acb2e
43
README.md
43
README.md
|
@ -89,6 +89,7 @@ frp also offers a P2P connect mode.
|
|||
* [HTTP X-Forwarded-For](#http-x-forwarded-for)
|
||||
* [Proxy Protocol](#proxy-protocol)
|
||||
* [Require HTTP Basic Auth (Password) for Web Services](#require-http-basic-auth-password-for-web-services)
|
||||
* [Require HTTPS client certificate for Web Services](#require-https-client-certificate-for-web-services)
|
||||
* [Custom Subdomain Names](#custom-subdomain-names)
|
||||
* [URL Routing](#url-routing)
|
||||
* [TCP Port Multiplexing](#tcp-port-multiplexing)
|
||||
|
@ -1046,11 +1047,11 @@ You can enable Proxy Protocol support in nginx to expose user's real IP in HTTP
|
|||
|
||||
### Require HTTP Basic Auth (Password) for Web Services
|
||||
|
||||
Anyone who can guess your tunnel URL can access your local web server unless you protect it with a password.
|
||||
Anyone who can guess your HTTP tunnel URL can access your local web server unless you protect it with a password.
|
||||
|
||||
This enforces HTTP Basic Auth on all requests with the username and password specified in frpc's configure file.
|
||||
|
||||
It can only be enabled when proxy type is http.
|
||||
It can only be enabled when proxy type is http. For https protection, see [Require HTTPS client certificate for Web Services](#require-https-client-certificate-for-web-services).
|
||||
|
||||
```toml
|
||||
# frpc.toml
|
||||
|
@ -1066,6 +1067,44 @@ httpPassword = "abc"
|
|||
|
||||
Visit `http://test.example.com` in the browser and now you are prompted to enter the username and password.
|
||||
|
||||
### Require HTTPS client certificate for Web Services
|
||||
|
||||
Anyone who can guess your HTTPS tunnel URL can access your local web server unless you protect it with a [Client Certificate](https://en.wikipedia.org/wiki/Transport_Layer_Security#Client-authenticated_TLS_handshake).
|
||||
|
||||
This [mutual authentication](https://en.wikipedia.org/wiki/Mutual_authentication) validates the HTTPS client's certificate on all requests, with each accepted certificate file specified in frpc's configure file.
|
||||
|
||||
It can only be enabled when proxy type is https. For http protection, see [Require HTTP Basic Auth (Password) for Web Services](#require-http-basic-auth-password-for-web-services).
|
||||
|
||||
```toml
|
||||
[[proxies]]
|
||||
name = "web"
|
||||
type = "https"
|
||||
customDomains = ["test.example.com"]
|
||||
|
||||
[proxies.plugin]
|
||||
type = "https2http"
|
||||
localAddr = "127.0.0.1:80"
|
||||
crtPath = server.crt"
|
||||
keyPath = "key.pem"
|
||||
clientCertificates = ["authorizedClient_cert.pem"]
|
||||
```
|
||||
|
||||
In this situation, the client certificate can be self-signed without any detriment to security. Multiple certificates can be generated and allowed to access the service.
|
||||
|
||||
Generate a .cert file **to use with frpc**, and a corresponding .pfx file **to install on Windows, Linux, or your browser**. The following instructions require the OpenSSL binary installed:
|
||||
|
||||
```bash
|
||||
# Windows
|
||||
openssl req -x509 -newkey rsa:4096 -keyout authorizedClient_cert.pem -out authorizedClient_key.pem -sha256 -days 3650 -nodes -subj "/CN=FRP Authentication Certificate"
|
||||
type authorizedClient_cert.pem authorizedClient_key.pem > authorizedClient.pem
|
||||
openssl pkcs12 -export -in authorizedClient.pem -out authorizedClient.pfx -name "FRP Authentication Certificate"
|
||||
|
||||
# Linux
|
||||
openssl req -x509 -newkey rsa:4096 -keyout authorizedClient_cert.pem -out authorizedClient_key.pem -sha256 -days 3650 -nodes -subj "/CN=FRP Authentication Certificate"
|
||||
cat authorizedClient_cert.pem authorizedClient_key.pem > authorizedClient.pem
|
||||
openssl pkcs12 -export -in authorizedClient.pem -out authorizedClient.pfx -name "FRP Authentication Certificate"
|
||||
```
|
||||
|
||||
### Custom Subdomain Names
|
||||
|
||||
It is convenient to use `subdomain` configure for http and https types when many people share one frps server.
|
||||
|
|
|
@ -116,13 +116,14 @@ type HTTPProxyPluginOptions struct {
|
|||
func (o *HTTPProxyPluginOptions) Complete() {}
|
||||
|
||||
type HTTPS2HTTPPluginOptions struct {
|
||||
Type string `json:"type,omitempty"`
|
||||
LocalAddr string `json:"localAddr,omitempty"`
|
||||
HostHeaderRewrite string `json:"hostHeaderRewrite,omitempty"`
|
||||
RequestHeaders HeaderOperations `json:"requestHeaders,omitempty"`
|
||||
EnableHTTP2 *bool `json:"enableHTTP2,omitempty"`
|
||||
CrtPath string `json:"crtPath,omitempty"`
|
||||
KeyPath string `json:"keyPath,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
LocalAddr string `json:"localAddr,omitempty"`
|
||||
HostHeaderRewrite string `json:"hostHeaderRewrite,omitempty"`
|
||||
RequestHeaders HeaderOperations `json:"requestHeaders,omitempty"`
|
||||
EnableHTTP2 *bool `json:"enableHTTP2,omitempty"`
|
||||
CrtPath string `json:"crtPath,omitempty"`
|
||||
KeyPath string `json:"keyPath,omitempty"`
|
||||
ClientCertificates []string `json:"clientCertificates,omitempty"`
|
||||
}
|
||||
|
||||
func (o *HTTPS2HTTPPluginOptions) Complete() {
|
||||
|
@ -130,13 +131,14 @@ func (o *HTTPS2HTTPPluginOptions) Complete() {
|
|||
}
|
||||
|
||||
type HTTPS2HTTPSPluginOptions struct {
|
||||
Type string `json:"type,omitempty"`
|
||||
LocalAddr string `json:"localAddr,omitempty"`
|
||||
HostHeaderRewrite string `json:"hostHeaderRewrite,omitempty"`
|
||||
RequestHeaders HeaderOperations `json:"requestHeaders,omitempty"`
|
||||
EnableHTTP2 *bool `json:"enableHTTP2,omitempty"`
|
||||
CrtPath string `json:"crtPath,omitempty"`
|
||||
KeyPath string `json:"keyPath,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
LocalAddr string `json:"localAddr,omitempty"`
|
||||
HostHeaderRewrite string `json:"hostHeaderRewrite,omitempty"`
|
||||
RequestHeaders HeaderOperations `json:"requestHeaders,omitempty"`
|
||||
EnableHTTP2 *bool `json:"enableHTTP2,omitempty"`
|
||||
CrtPath string `json:"crtPath,omitempty"`
|
||||
KeyPath string `json:"keyPath,omitempty"`
|
||||
ClientCertificates []string `json:"clientCertificates,omitempty"`
|
||||
}
|
||||
|
||||
func (o *HTTPS2HTTPSPluginOptions) Complete() {
|
||||
|
|
|
@ -19,6 +19,7 @@ package plugin
|
|||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"io"
|
||||
stdlog "log"
|
||||
|
@ -91,6 +92,33 @@ func NewHTTPS2HTTPPlugin(options v1.ClientPluginOptions) (Plugin, error) {
|
|||
return nil, fmt.Errorf("gen TLS config error: %v", err)
|
||||
}
|
||||
|
||||
if len(p.opts.ClientCertificates) > 0 {
|
||||
certs, err := transport.LoadCertificatesFromFiles(p.opts.ClientCertificates)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("loading Client Certificates failed: %v", err)
|
||||
}
|
||||
|
||||
tlsConfig.ClientAuth = tls.RequireAnyClientCert
|
||||
tlsConfig.VerifyPeerCertificate = func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
|
||||
if len(rawCerts) == 0 {
|
||||
return fmt.Errorf("no client certificate provided")
|
||||
}
|
||||
|
||||
clientCert, err := x509.ParseCertificate(rawCerts[0])
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse client certificate: %w", err)
|
||||
}
|
||||
|
||||
for _, allowedCert := range certs {
|
||||
if clientCert.Equal(allowedCert) {
|
||||
return nil //match found, accept
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("client certificate not recognized")
|
||||
}
|
||||
}
|
||||
|
||||
p.s = &http.Server{
|
||||
Handler: handler,
|
||||
ReadHeaderTimeout: 60 * time.Second,
|
||||
|
|
|
@ -19,6 +19,7 @@ package plugin
|
|||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"io"
|
||||
stdlog "log"
|
||||
|
@ -97,6 +98,33 @@ func NewHTTPS2HTTPSPlugin(options v1.ClientPluginOptions) (Plugin, error) {
|
|||
return nil, fmt.Errorf("gen TLS config error: %v", err)
|
||||
}
|
||||
|
||||
if len(p.opts.ClientCertificates) > 0 {
|
||||
certs, err := transport.LoadCertificatesFromFiles(p.opts.ClientCertificates)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("loading Client Certificates failed: %v", err)
|
||||
}
|
||||
|
||||
tlsConfig.ClientAuth = tls.RequireAnyClientCert
|
||||
tlsConfig.VerifyPeerCertificate = func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
|
||||
if len(rawCerts) == 0 {
|
||||
return fmt.Errorf("no client certificate provided")
|
||||
}
|
||||
|
||||
clientCert, err := x509.ParseCertificate(rawCerts[0])
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse client certificate: %w", err)
|
||||
}
|
||||
|
||||
for _, allowedCert := range certs {
|
||||
if clientCert.Equal(allowedCert) {
|
||||
return nil //match found, accept
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("client certificate not recognized")
|
||||
}
|
||||
}
|
||||
|
||||
p.s = &http.Server{
|
||||
Handler: handler,
|
||||
ReadHeaderTimeout: 60 * time.Second,
|
||||
|
|
|
@ -20,6 +20,7 @@ import (
|
|||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"os"
|
||||
)
|
||||
|
@ -140,3 +141,28 @@ func NewRandomPrivateKey() ([]byte, error) {
|
|||
})
|
||||
return keyPEM, nil
|
||||
}
|
||||
|
||||
func LoadCertificatesFromFiles(certFiles []string) ([]*x509.Certificate, error) {
|
||||
var certificates []*x509.Certificate
|
||||
|
||||
for _, file := range certFiles {
|
||||
certPEM, err := os.ReadFile(file)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read certificate file %s: %w", file, err)
|
||||
}
|
||||
|
||||
block, _ := pem.Decode(certPEM)
|
||||
if block == nil {
|
||||
return nil, fmt.Errorf("failed to decode PEM block")
|
||||
}
|
||||
|
||||
cert, err := x509.ParseCertificate(block.Bytes)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse certificate file %s: %w", file, err)
|
||||
}
|
||||
|
||||
certificates = append(certificates, cert)
|
||||
}
|
||||
|
||||
return certificates, nil
|
||||
}
|
||||
|
|
|
@ -236,67 +236,126 @@ var _ = ginkgo.Describe("[Feature: Client-Plugins]", func() {
|
|||
Ensure()
|
||||
})
|
||||
|
||||
ginkgo.It("https2http", func() {
|
||||
generator := &cert.SelfSignedCertGenerator{}
|
||||
artifacts, err := generator.Generate("example.com")
|
||||
framework.ExpectNoError(err)
|
||||
crtPath := f.WriteTempFile("server.crt", string(artifacts.Cert))
|
||||
keyPath := f.WriteTempFile("server.key", string(artifacts.Key))
|
||||
ginkgo.Describe("https2http", func() {
|
||||
ginkgo.It("without client certificate requirement", func() {
|
||||
generator := &cert.SelfSignedCertGenerator{}
|
||||
artifacts, err := generator.Generate("example.com")
|
||||
framework.ExpectNoError(err)
|
||||
crtPath := f.WriteTempFile("server.crt", string(artifacts.Cert))
|
||||
keyPath := f.WriteTempFile("server.key", string(artifacts.Key))
|
||||
|
||||
serverConf := consts.DefaultServerConfig
|
||||
vhostHTTPSPort := f.AllocPort()
|
||||
serverConf += fmt.Sprintf(`
|
||||
vhostHTTPSPort = %d
|
||||
`, vhostHTTPSPort)
|
||||
serverConf := consts.DefaultServerConfig
|
||||
vhostHTTPSPort := f.AllocPort()
|
||||
serverConf += fmt.Sprintf(`
|
||||
vhostHTTPSPort = %d
|
||||
`, vhostHTTPSPort)
|
||||
|
||||
localPort := f.AllocPort()
|
||||
clientConf := consts.DefaultClientConfig + fmt.Sprintf(`
|
||||
[[proxies]]
|
||||
name = "https2http"
|
||||
type = "https"
|
||||
customDomains = ["example.com"]
|
||||
[proxies.plugin]
|
||||
type = "https2http"
|
||||
localAddr = "127.0.0.1:%d"
|
||||
crtPath = "%s"
|
||||
keyPath = "%s"
|
||||
`, localPort, crtPath, keyPath)
|
||||
localPort := f.AllocPort()
|
||||
clientConf := consts.DefaultClientConfig + fmt.Sprintf(`
|
||||
[[proxies]]
|
||||
name = "https2http"
|
||||
type = "https"
|
||||
customDomains = ["example.com"]
|
||||
[proxies.plugin]
|
||||
type = "https2http"
|
||||
localAddr = "127.0.0.1:%d"
|
||||
crtPath = "%s"
|
||||
keyPath = "%s"
|
||||
`, localPort, crtPath, keyPath)
|
||||
|
||||
f.RunProcesses([]string{serverConf}, []string{clientConf})
|
||||
f.RunProcesses([]string{serverConf}, []string{clientConf})
|
||||
|
||||
localServer := httpserver.New(
|
||||
httpserver.WithBindPort(localPort),
|
||||
httpserver.WithResponse([]byte("test")),
|
||||
)
|
||||
f.RunServer("", localServer)
|
||||
localServer := httpserver.New(
|
||||
httpserver.WithBindPort(localPort),
|
||||
httpserver.WithResponse([]byte("test")),
|
||||
)
|
||||
f.RunServer("", localServer)
|
||||
|
||||
framework.NewRequestExpect(f).
|
||||
Port(vhostHTTPSPort).
|
||||
RequestModify(func(r *request.Request) {
|
||||
r.HTTPS().HTTPHost("example.com").TLSConfig(&tls.Config{
|
||||
ServerName: "example.com",
|
||||
InsecureSkipVerify: true,
|
||||
})
|
||||
}).
|
||||
ExpectResp([]byte("test")).
|
||||
Ensure()
|
||||
framework.NewRequestExpect(f).
|
||||
Port(vhostHTTPSPort).
|
||||
RequestModify(func(r *request.Request) {
|
||||
r.HTTPS().HTTPHost("example.com").TLSConfig(&tls.Config{
|
||||
ServerName: "example.com",
|
||||
InsecureSkipVerify: true,
|
||||
})
|
||||
}).
|
||||
ExpectResp([]byte("test")).
|
||||
Ensure()
|
||||
})
|
||||
|
||||
ginkgo.It("with client certificate requirement", func() {
|
||||
generator := &cert.SelfSignedCertGenerator{}
|
||||
artifacts, err := generator.Generate("example.com")
|
||||
framework.ExpectNoError(err)
|
||||
crtPath := f.WriteTempFile("server.crt", string(artifacts.Cert))
|
||||
keyPath := f.WriteTempFile("server.key", string(artifacts.Key))
|
||||
|
||||
artifacts, err = generator.Generate("127.0.0.1")
|
||||
framework.ExpectNoError(err)
|
||||
clientCrtPath := f.WriteTempFile("client.crt", string(artifacts.Cert))
|
||||
clientKeyPath := f.WriteTempFile("client.key", string(artifacts.Key))
|
||||
|
||||
serverConf := consts.DefaultServerConfig
|
||||
vhostHTTPSPort := f.AllocPort()
|
||||
serverConf += fmt.Sprintf(`
|
||||
vhostHTTPSPort = %d
|
||||
`, vhostHTTPSPort)
|
||||
|
||||
localPort := f.AllocPort()
|
||||
clientConf := consts.DefaultClientConfig + fmt.Sprintf(`
|
||||
[[proxies]]
|
||||
name = "https2http"
|
||||
type = "https"
|
||||
customDomains = ["example.com"]
|
||||
[proxies.plugin]
|
||||
type = "https2http"
|
||||
localAddr = "127.0.0.1:%d"
|
||||
crtPath = "%s"
|
||||
keyPath = "%s"
|
||||
clientCertificates = ["%s"]
|
||||
`, localPort, crtPath, keyPath, clientCrtPath)
|
||||
|
||||
f.RunProcesses([]string{serverConf}, []string{clientConf})
|
||||
|
||||
localServer := httpserver.New(
|
||||
httpserver.WithBindPort(localPort),
|
||||
httpserver.WithResponse([]byte("test")),
|
||||
)
|
||||
f.RunServer("", localServer)
|
||||
|
||||
clientCertificate, err := tls.LoadX509KeyPair(clientCrtPath, clientKeyPath)
|
||||
framework.ExpectNoError(err)
|
||||
|
||||
framework.NewRequestExpect(f).
|
||||
Port(vhostHTTPSPort).
|
||||
RequestModify(func(r *request.Request) {
|
||||
r.HTTPS().HTTPHost("example.com").TLSConfig(&tls.Config{
|
||||
ServerName: "example.com",
|
||||
InsecureSkipVerify: true,
|
||||
Certificates: []tls.Certificate{clientCertificate},
|
||||
})
|
||||
}).
|
||||
ExpectResp([]byte("test")).
|
||||
Ensure()
|
||||
})
|
||||
})
|
||||
|
||||
ginkgo.It("https2https", func() {
|
||||
generator := &cert.SelfSignedCertGenerator{}
|
||||
artifacts, err := generator.Generate("example.com")
|
||||
framework.ExpectNoError(err)
|
||||
crtPath := f.WriteTempFile("server.crt", string(artifacts.Cert))
|
||||
keyPath := f.WriteTempFile("server.key", string(artifacts.Key))
|
||||
ginkgo.Describe("https2https", func() {
|
||||
ginkgo.It("without client certificate requirement", func() {
|
||||
generator := &cert.SelfSignedCertGenerator{}
|
||||
artifacts, err := generator.Generate("example.com")
|
||||
framework.ExpectNoError(err)
|
||||
crtPath := f.WriteTempFile("server.crt", string(artifacts.Cert))
|
||||
keyPath := f.WriteTempFile("server.key", string(artifacts.Key))
|
||||
|
||||
serverConf := consts.DefaultServerConfig
|
||||
vhostHTTPSPort := f.AllocPort()
|
||||
serverConf += fmt.Sprintf(`
|
||||
serverConf := consts.DefaultServerConfig
|
||||
vhostHTTPSPort := f.AllocPort()
|
||||
serverConf += fmt.Sprintf(`
|
||||
vhostHTTPSPort = %d
|
||||
`, vhostHTTPSPort)
|
||||
|
||||
localPort := f.AllocPort()
|
||||
clientConf := consts.DefaultClientConfig + fmt.Sprintf(`
|
||||
localPort := f.AllocPort()
|
||||
clientConf := consts.DefaultClientConfig + fmt.Sprintf(`
|
||||
[[proxies]]
|
||||
name = "https2https"
|
||||
type = "https"
|
||||
|
@ -308,27 +367,87 @@ var _ = ginkgo.Describe("[Feature: Client-Plugins]", func() {
|
|||
keyPath = "%s"
|
||||
`, localPort, crtPath, keyPath)
|
||||
|
||||
f.RunProcesses([]string{serverConf}, []string{clientConf})
|
||||
f.RunProcesses([]string{serverConf}, []string{clientConf})
|
||||
|
||||
tlsConfig, err := transport.NewServerTLSConfig("", "", "")
|
||||
framework.ExpectNoError(err)
|
||||
localServer := httpserver.New(
|
||||
httpserver.WithBindPort(localPort),
|
||||
httpserver.WithResponse([]byte("test")),
|
||||
httpserver.WithTLSConfig(tlsConfig),
|
||||
)
|
||||
f.RunServer("", localServer)
|
||||
tlsConfig, err := transport.NewServerTLSConfig("", "", "")
|
||||
framework.ExpectNoError(err)
|
||||
localServer := httpserver.New(
|
||||
httpserver.WithBindPort(localPort),
|
||||
httpserver.WithResponse([]byte("test")),
|
||||
httpserver.WithTLSConfig(tlsConfig),
|
||||
)
|
||||
f.RunServer("", localServer)
|
||||
|
||||
framework.NewRequestExpect(f).
|
||||
Port(vhostHTTPSPort).
|
||||
RequestModify(func(r *request.Request) {
|
||||
r.HTTPS().HTTPHost("example.com").TLSConfig(&tls.Config{
|
||||
ServerName: "example.com",
|
||||
InsecureSkipVerify: true,
|
||||
})
|
||||
}).
|
||||
ExpectResp([]byte("test")).
|
||||
Ensure()
|
||||
})
|
||||
|
||||
ginkgo.It("with client certificate requirement", func() {
|
||||
generator := &cert.SelfSignedCertGenerator{}
|
||||
artifacts, err := generator.Generate("example.com")
|
||||
framework.ExpectNoError(err)
|
||||
crtPath := f.WriteTempFile("server.crt", string(artifacts.Cert))
|
||||
keyPath := f.WriteTempFile("server.key", string(artifacts.Key))
|
||||
artifacts, err = generator.Generate("127.0.0.1")
|
||||
framework.ExpectNoError(err)
|
||||
clientCrtPath := f.WriteTempFile("client.crt", string(artifacts.Cert))
|
||||
clientKeyPath := f.WriteTempFile("client.key", string(artifacts.Key))
|
||||
|
||||
serverConf := consts.DefaultServerConfig
|
||||
vhostHTTPSPort := f.AllocPort()
|
||||
serverConf += fmt.Sprintf(`
|
||||
vhostHTTPSPort = %d
|
||||
`, vhostHTTPSPort)
|
||||
|
||||
localPort := f.AllocPort()
|
||||
clientConf := consts.DefaultClientConfig + fmt.Sprintf(`
|
||||
[[proxies]]
|
||||
name = "https2https"
|
||||
type = "https"
|
||||
customDomains = ["example.com"]
|
||||
[proxies.plugin]
|
||||
type = "https2https"
|
||||
localAddr = "127.0.0.1:%d"
|
||||
crtPath = "%s"
|
||||
keyPath = "%s"
|
||||
clientCertificates = ["%s"]
|
||||
`, localPort, crtPath, keyPath, clientCrtPath)
|
||||
|
||||
f.RunProcesses([]string{serverConf}, []string{clientConf})
|
||||
|
||||
tlsConfig, err := transport.NewServerTLSConfig("", "", "")
|
||||
framework.ExpectNoError(err)
|
||||
localServer := httpserver.New(
|
||||
httpserver.WithBindPort(localPort),
|
||||
httpserver.WithResponse([]byte("test")),
|
||||
httpserver.WithTLSConfig(tlsConfig),
|
||||
)
|
||||
f.RunServer("", localServer)
|
||||
|
||||
clientCertificate, err := tls.LoadX509KeyPair(clientCrtPath, clientKeyPath)
|
||||
framework.ExpectNoError(err)
|
||||
|
||||
framework.NewRequestExpect(f).
|
||||
Port(vhostHTTPSPort).
|
||||
RequestModify(func(r *request.Request) {
|
||||
r.HTTPS().HTTPHost("example.com").TLSConfig(&tls.Config{
|
||||
ServerName: "example.com",
|
||||
InsecureSkipVerify: true,
|
||||
Certificates: []tls.Certificate{clientCertificate},
|
||||
})
|
||||
}).
|
||||
ExpectResp([]byte("test")).
|
||||
Ensure()
|
||||
})
|
||||
|
||||
framework.NewRequestExpect(f).
|
||||
Port(vhostHTTPSPort).
|
||||
RequestModify(func(r *request.Request) {
|
||||
r.HTTPS().HTTPHost("example.com").TLSConfig(&tls.Config{
|
||||
ServerName: "example.com",
|
||||
InsecureSkipVerify: true,
|
||||
})
|
||||
}).
|
||||
ExpectResp([]byte("test")).
|
||||
Ensure()
|
||||
})
|
||||
|
||||
ginkgo.Describe("http2http", func() {
|
||||
|
|
Loading…
Reference in New Issue