Add support for mTLS
This commit is contained in:
parent
4524397d4f
commit
70b5a216b0
20 changed files with 1051 additions and 57 deletions
280
docs/using_mtls.md
Normal file
280
docs/using_mtls.md
Normal file
|
@ -0,0 +1,280 @@
|
|||
# Using mTLS with wstunnel
|
||||
|
||||
## Generating keys and certificates
|
||||
|
||||
WARNING: The following instructions are intended for using in a development / testing environment. They are **not**
|
||||
intended for setting up a production environment. In a production environment you could use a solution such
|
||||
as [OpenBao](https://openbao.org/) (opensource fork of Hashicorp Vault), [EJBCA](https://www.ejbca.org/)
|
||||
or [Dogtag PKI](https://www.dogtagpki.org/) for example.
|
||||
|
||||
These steps are based on: https://jamielinux.com/docs/openssl-certificate-authority/
|
||||
|
||||
In order to setup wstunnel to authenticate clients with certificates (mTLS) one must have a certificate authority for
|
||||
signing client certificates. In this example we will create a certificate authority using OpenSSL.
|
||||
|
||||
Run these commands from a directory which we will use to store the CA's files. For example under `~/wstunnel/client_ca`
|
||||
|
||||
```shell
|
||||
$ mkdir -p $HOME/wstunnel/ca/{certs,csr,crl,newcerts,private}
|
||||
$ cd $HOME/wstunnel/ca/
|
||||
$ echo 1000 > serial
|
||||
$ touch index.txt
|
||||
```
|
||||
|
||||
Create the OpenSSL CA configuration. Beware some entries are escaped so they can be easily written out with `cat`:
|
||||
|
||||
```shell
|
||||
$ cat > ./openssl.cnf << END_OF_FILE
|
||||
[ ca ]
|
||||
default_ca = CA_default
|
||||
|
||||
[ CA_default ]
|
||||
# Directory and file locations.
|
||||
dir = $HOME/wstunnel/ca
|
||||
certs = \$dir/certs
|
||||
crl_dir = \$dir/crl
|
||||
new_certs_dir = \$dir/newcerts
|
||||
database = \$dir/index.txt
|
||||
serial = \$dir/serial
|
||||
RANDFILE = \$dir/private/.rand
|
||||
|
||||
# The root key and root certificate.
|
||||
private_key = \$dir/private/ca.key.pem
|
||||
certificate = \$dir/certs/ca.cert.pem
|
||||
|
||||
# For certificate revocation lists.
|
||||
crlnumber = \$dir/crlnumber
|
||||
crl = \$dir/crl/ca.crl.pem
|
||||
crl_extensions = crl_ext
|
||||
default_crl_days = 30
|
||||
|
||||
# SHA-1 is deprecated, so use SHA-2 instead.
|
||||
default_md = sha256
|
||||
|
||||
name_opt = ca_default
|
||||
cert_opt = ca_default
|
||||
default_days = 375
|
||||
preserve = no
|
||||
policy = policy_loose
|
||||
|
||||
[ policy_loose ]
|
||||
countryName = optional
|
||||
stateOrProvinceName = optional
|
||||
localityName = optional
|
||||
organizationName = optional
|
||||
organizationalUnitName = optional
|
||||
commonName = optional
|
||||
emailAddress = optional
|
||||
|
||||
[ req ]
|
||||
# Configuration for a certificate signing request.
|
||||
default_bits = 2048
|
||||
distinguished_name = req_distinguished_name
|
||||
string_mask = utf8only
|
||||
# SHA-1 is deprecated, so use SHA-2 instead.
|
||||
default_md = sha256
|
||||
# Extension to add when the -x509 option is used.
|
||||
x509_extensions = v3_ca
|
||||
|
||||
[ req_distinguished_name ]
|
||||
# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
|
||||
countryName = Country Name (2 letter code)
|
||||
stateOrProvinceName = State or Province Name
|
||||
localityName = Locality Name
|
||||
0.organizationName = Organization Name
|
||||
organizationalUnitName = Organizational Unit Name
|
||||
commonName = Common Name
|
||||
emailAddress = Email Address
|
||||
|
||||
# Optionally, specify some defaults.
|
||||
countryName_default = GB
|
||||
stateOrProvinceName_default = England
|
||||
localityName_default =
|
||||
0.organizationName_default = wstunnel development
|
||||
#organizationalUnitName_default =
|
||||
#emailAddress_default =
|
||||
|
||||
[ v3_ca ]
|
||||
# Configuration for a certificate authority.
|
||||
subjectKeyIdentifier = hash
|
||||
authorityKeyIdentifier = keyid:always,issuer
|
||||
basicConstraints = critical, CA:true
|
||||
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
|
||||
|
||||
[ client_cert ]
|
||||
# Configuration for client certificates.
|
||||
basicConstraints = CA:FALSE
|
||||
nsCertType = client, email
|
||||
nsComment = "OpenSSL Generated Client Certificate"
|
||||
subjectKeyIdentifier = hash
|
||||
authorityKeyIdentifier = keyid,issuer
|
||||
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
|
||||
extendedKeyUsage = clientAuth, emailProtection
|
||||
|
||||
[ server_cert ]
|
||||
# Configuration for server certificates.
|
||||
basicConstraints = CA:FALSE
|
||||
nsCertType = server
|
||||
nsComment = "OpenSSL Generated Server Certificate"
|
||||
subjectKeyIdentifier = hash
|
||||
authorityKeyIdentifier = keyid,issuer:always
|
||||
keyUsage = critical, digitalSignature, keyEncipherment
|
||||
extendedKeyUsage = serverAuth
|
||||
|
||||
[ crl_ext ]
|
||||
# Configuration for CRLs.
|
||||
authorityKeyIdentifier=keyid:always
|
||||
END_OF_FILE
|
||||
```
|
||||
|
||||
Generate the private key of the certificate authority. Normally you would encrypt it and set a passphrase on it but for
|
||||
development purposes we will leave it unencrypted.
|
||||
|
||||
```shell
|
||||
$ cd $HOME/wstunnel/ca/
|
||||
$ openssl genrsa -out private/ca.key.pem 4096
|
||||
```
|
||||
|
||||
The certificate of the root certificate authority is self-signed (since it is the root of trust):
|
||||
|
||||
```shell
|
||||
$ openssl req -config openssl.cnf \
|
||||
-key private/ca.key.pem \
|
||||
-new -x509 -days 7300 -sha256 -extensions v3_ca \
|
||||
-out certs/ca.cert.pem
|
||||
---8<------
|
||||
Country Name (2 letter code) [GB]:
|
||||
State or Province Name [England]:
|
||||
Locality Name []:
|
||||
Organization Name [Alice Ltd]:
|
||||
Organizational Unit Name []:
|
||||
Common Name []:wstunnel Development Root CA
|
||||
Email Address []:
|
||||
```
|
||||
|
||||
Generate a key for the wstunnel server, generate a certificate signing request (CSR) and create a certificate with our
|
||||
CA for the CSR:
|
||||
|
||||
```shell
|
||||
$ openssl genrsa -out private/wstunnel-server.pem 2048
|
||||
$ openssl req -config openssl.cnf \
|
||||
-key private/wstunnel-server.pem \
|
||||
-new -sha256 -out csr/wstunnel-server.csr.pem
|
||||
---8<------
|
||||
Country Name (2 letter code) [GB]:
|
||||
State or Province Name [England]:
|
||||
Locality Name []:
|
||||
Organization Name [Alice Ltd]:
|
||||
Organizational Unit Name []:
|
||||
Common Name []:wstunnel Development Server
|
||||
Email Address []:
|
||||
|
||||
$ openssl ca -config openssl.cnf \
|
||||
-extensions server_cert -days 375 -notext -md sha256 \
|
||||
-in csr/wstunnel-server.csr.pem \
|
||||
-out certs/wstunnel-server.cert.pem
|
||||
---8<------
|
||||
Sign the certificate? [y/n]:y
|
||||
1 out of 1 certificate requests certified, commit? [y/n]y
|
||||
```
|
||||
|
||||
Next we do the same thing (generate key, create request, sign request) but then for a wstunnel client:
|
||||
|
||||
```shell
|
||||
$ openssl genrsa -out private/wstunnel-client-1.pem 2048
|
||||
$ openssl req -config openssl.cnf \
|
||||
-key private/wstunnel-client-1.pem \
|
||||
-new -sha256 -out csr/wstunnel-client-1.csr.pem
|
||||
---8<------
|
||||
Country Name (2 letter code) [GB]:
|
||||
State or Province Name [England]:
|
||||
Locality Name []:
|
||||
Organization Name [Alice Ltd]:
|
||||
Organizational Unit Name []:
|
||||
Common Name []:wstunnel Development Client 1
|
||||
Email Address []:
|
||||
|
||||
$ openssl ca -config openssl.cnf \
|
||||
-extensions client_cert -days 375 -notext -md sha256 \
|
||||
-in csr/wstunnel-client-1.csr.pem \
|
||||
-out certs/wstunnel-client-1.cert.pem
|
||||
---8<------
|
||||
Sign the certificate? [y/n]:y
|
||||
1 out of 1 certificate requests certified, commit? [y/n]y
|
||||
```
|
||||
|
||||
## Using mTLS on the wstunnel server side
|
||||
|
||||
This section assumes you have generated the certificate authority, keys, certificates, etc. as outlined in the "
|
||||
Generating keys and certificates" section.
|
||||
|
||||
Start a `wstunnel` server and make it use the server key pair certificate (`--tls-certificate` and `--tls-private-key`)
|
||||
and configure it to authenticate clients via mTLS (`--tls-client-ca-certs`):
|
||||
|
||||
```shell
|
||||
$ wstunnel server \
|
||||
--tls-certificate ./certs/wstunnel-server.cert.pem \
|
||||
--tls-private-key ./private/wstunnel-server.pem \
|
||||
--tls-client-ca-certs ./certs/ca.cert.pem \
|
||||
wss://0.0.0.0:8443
|
||||
```
|
||||
|
||||
### Testing
|
||||
|
||||
You can use `openssl` to test connecting with the client certificate to the wstunnel server:
|
||||
|
||||
```shell
|
||||
$ openssl s_client -connect 127.0.0.1:8443 \
|
||||
-key ./private/wstunnel-client-1.pem \
|
||||
-cert ./certs/wstunnel-client-1.cert.pem \
|
||||
-cert_chain ./certs/ca.cert.pem \
|
||||
-state -debug
|
||||
---8<-----
|
||||
Acceptable client certificate CA names
|
||||
C = GB, ST = England, O = Alice Ltd, CN = wstunnel Development Root CA
|
||||
---8<-----
|
||||
```
|
||||
|
||||
Similarly, you can use `openssl` to test what happens if you try to connect with a client certificate which is not
|
||||
signed by our CA by generating a self-signed certificate:
|
||||
|
||||
```shell
|
||||
$ openssl req -nodes -x509 -sha256 -newkey rsa:4096 \
|
||||
-keyout faux.key.pem \
|
||||
-out faux.crt.pem \
|
||||
-days 356 \
|
||||
-subj "/C=GB/ST=England/L=London/O=ACME Corp/OU=IT Dept/CN=Development Faux Client"
|
||||
$ openssl s_client -connect 127.0.0.1:8443 \
|
||||
-key faux.key.pem \
|
||||
-cert faux.crt.pem \
|
||||
-cert_chain ./certs/ca.cert.pem \
|
||||
-state -debug
|
||||
----8<----
|
||||
SSL3 alert read:fatal:certificate unknown
|
||||
---8<-----
|
||||
```
|
||||
|
||||
Trying to connect without the client presenting any certificate at all will also fail (the `--cacert` flag only
|
||||
tells `curl` which CA certificate to use to verify the certificate of the **server** with):
|
||||
|
||||
```shell
|
||||
$ curl -vvv --cacert ./certs/ca.cert.pem https://127.0.0.1:8443
|
||||
```
|
||||
|
||||
## Using mTLS on the wstunnel client side
|
||||
|
||||
This section assumes you have generated the certificate authority, keys, certificates, etc. as outlined in the "
|
||||
Generating keys and certificates" section. It also assumes you have a running wstunnel server with mTLS configured. For
|
||||
example as setup in the `Using mTLS on the wstunnel server side` section.
|
||||
|
||||
```shell
|
||||
$ wstunnel client \
|
||||
--tls-certificate ./certs/wstunnel-client-1.cert.pem \
|
||||
--tls-private-key ./private/wstunnel-client-1.pem \
|
||||
-L tcp://1212:localhost:1313 \
|
||||
wss://127.0.0.1:8443
|
||||
|
||||
$ nc 127.0.0.1 1212
|
||||
```
|
||||
|
||||
|
33
mTLS/certs/ca.cert.pem
Normal file
33
mTLS/certs/ca.cert.pem
Normal file
|
@ -0,0 +1,33 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
-----END CERTIFICATE-----
|
30
mTLS/certs/wstunnel-client-1.cert.pem
Normal file
30
mTLS/certs/wstunnel-client-1.cert.pem
Normal file
|
@ -0,0 +1,30 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIFDTCCAvWgAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCR0Ix
|
||||
EDAOBgNVBAgMB0VuZ2xhbmQxHTAbBgNVBAoMFHdzdHVubmVsIGRldmVsb3BtZW50
|
||||
MSUwIwYDVQQDDBx3c3R1bm5lbCBEZXZlbG9wbWVudCBSb290IENBMB4XDTI0MDQx
|
||||
OTA2NDAwMVoXDTI1MDQyOTA2NDAwMVowZjELMAkGA1UEBhMCR0IxEDAOBgNVBAgM
|
||||
B0VuZ2xhbmQxHTAbBgNVBAoMFHdzdHVubmVsIGRldmVsb3BtZW50MSYwJAYDVQQD
|
||||
DB13c3R1bm5lbCBEZXZlbG9wbWVudCBDbGllbnQgMTCCASIwDQYJKoZIhvcNAQEB
|
||||
BQADggEPADCCAQoCggEBAMI87ijKk6jMWPcJtkcK0AKQ5rbrkLMACkCliB4v11gi
|
||||
kMbqMIT8eQHEfKmTu5uuisutMNrPqZQXCXgoYbUk0IuRuzXtmuZSMAzA5X/xWAU4
|
||||
fpbXwS5vd21impE6UZkXGQunngD5WNEn4sm7t4g/ioCTqMdv+svBMTaWXUIwpgEO
|
||||
KtMsaC9FVQxYe9zyJPN0QaSU6NMOM2LwQNzh51vtJyVT9lCixTQWM1Q5bTbQrVrz
|
||||
MdRZHEX6ogEg/WPUTaO1y+InBAVn6DzcLwslLPV7s4/6l6hmNEkZWBqz77KFc5H1
|
||||
Ol7PRInYLt8BlACb1MIlE81RYLIW1THMN7G4eVRrgq8CAwEAAaOBxTCBwjAJBgNV
|
||||
HRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIFoDAzBglghkgBhvhCAQ0EJhYkT3BlblNT
|
||||
TCBHZW5lcmF0ZWQgQ2xpZW50IENlcnRpZmljYXRlMB0GA1UdDgQWBBS3UAwJmyci
|
||||
WunqYPI4DSNTMjpBIjAfBgNVHSMEGDAWgBTtbfEPPuXC2O2AOHxRPWgCoo07wzAO
|
||||
BgNVHQ8BAf8EBAMCBeAwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMA0G
|
||||
CSqGSIb3DQEBCwUAA4ICAQCyUuIIIylwAEJ0x4cvwuuV65MnsDiNktpqllsih/wo
|
||||
bfutcvGy//FOMk/04YYJZbLAOfvNLakp3A+oEGOuYaMJst9e2zGXRI2AqPZzxxkY
|
||||
P1GAfnxiLtjHltUMlpMrx+thGWqKYYAXim8TY3O3hjXkrpE8vOTG5vpQmMMmo2/y
|
||||
Po++eiVbd/+cXDdMwbum31rexpN0JC9SBF9GmrHoKekPpQ+gGJe6HAVAEWV2UMId
|
||||
MEtKzk8RrwySfn6oErNkOD+4DF9eJogl2cjlfl5y+DHeadAtYDcXS8lEvgJ6LwsE
|
||||
ftDMhtY1FBrq5nCxip2Fk6uB08wypcHXC/+sXP71tCBuQiaHCW/GTaFlWQijfepq
|
||||
yh/zx9narIxpTFCVfX1hiy6uYkehvWiBsds0LNwVzSUEC+wfxuwGlVWRtalf/K9e
|
||||
+1CHraMP0VjsSO+U5CWKuNdPffq/V/v2nyKzkbakssZex3Xoy0sWZ/i0tl2AD+K8
|
||||
p9SRRuWShv2q3qZUfbKRgGnIlsCJNK3xUlak6HTPpL/woV3QfakO81E06x/Mlgvm
|
||||
9PXA9t0yp+hyk0S9mgwAiL5/s6pm+A0WsSjJ6ohl2jsktvAYgFy7S/rFL7ZC7kN1
|
||||
TH+dlY/0Cj5yBlA0G0B2VEoW0nrnUGfA6xxnl1Tv096bhxCUKg9YC+/VDRgIVyX4
|
||||
uw==
|
||||
-----END CERTIFICATE-----
|
32
mTLS/certs/wstunnel-server.cert.pem
Normal file
32
mTLS/certs/wstunnel-server.cert.pem
Normal file
|
@ -0,0 +1,32 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIFhzCCA2+gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCR0Ix
|
||||
EDAOBgNVBAgMB0VuZ2xhbmQxHTAbBgNVBAoMFHdzdHVubmVsIGRldmVsb3BtZW50
|
||||
MSUwIwYDVQQDDBx3c3R1bm5lbCBEZXZlbG9wbWVudCBSb290IENBMB4XDTI0MDQx
|
||||
OTA2MzkwMloXDTI1MDQyOTA2MzkwMlowZDELMAkGA1UEBhMCR0IxEDAOBgNVBAgM
|
||||
B0VuZ2xhbmQxHTAbBgNVBAoMFHdzdHVubmVsIGRldmVsb3BtZW50MSQwIgYDVQQD
|
||||
DBt3c3R1bm5lbCBEZXZlbG9wbWVudCBTZXJ2ZXIwggEiMA0GCSqGSIb3DQEBAQUA
|
||||
A4IBDwAwggEKAoIBAQCukQ8xc1LHj+NxSGK714s3jMBJdzuaPsUh5tVj5I+2SMNf
|
||||
t6SmLxRm14meUChoiyIaZ5K3Nd8F8+PzF2CmdH6dTY+XzZv2b0Ap544qNJ2trHwi
|
||||
J9AR8zYOoCnHnlc4p7NatQsSJ8HozhVuPSBA46xtTUsHUFSVZt0kfGBDDXDtsnU1
|
||||
e3BWqvjyndvqSF/TF1YX1CakuY+rNKKyVUOYHE/dncMdlBA+G09NiDYhrSybiadW
|
||||
OU3D++oJmOFC32Mz2r/sMTqmHgb/NoNA83br5I8AUmhFcZTNE5pbjLgbukQrlA1s
|
||||
noTCNCHK39YvuC/DGFONWiwQdMCITn3S7z9k4/ObAgMBAAGjggFAMIIBPDAJBgNV
|
||||
HRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIGQDAzBglghkgBhvhCAQ0EJhYkT3BlblNT
|
||||
TCBHZW5lcmF0ZWQgU2VydmVyIENlcnRpZmljYXRlMB0GA1UdDgQWBBTevpkP7cSW
|
||||
XnmhdtxQej4tBVMd1DCBogYDVR0jBIGaMIGXgBTtbfEPPuXC2O2AOHxRPWgCoo07
|
||||
w6FppGcwZTELMAkGA1UEBhMCR0IxEDAOBgNVBAgMB0VuZ2xhbmQxHTAbBgNVBAoM
|
||||
FHdzdHVubmVsIGRldmVsb3BtZW50MSUwIwYDVQQDDBx3c3R1bm5lbCBEZXZlbG9w
|
||||
bWVudCBSb290IENBghRNOEar2B6EMORpy15L+8cSdEUR2zAOBgNVHQ8BAf8EBAMC
|
||||
BaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggIBABztA4Vm
|
||||
ROMZmtMmcjxV5hsNXs1iB50MBjjMvsLS2bVSfqRiENDnSrwHrGtvvcaX2sLrKtld
|
||||
Xv+zgIMU7n4UxAIPiJa+X47+glyQZXpK7MNpzQgsCtNCUyI6flqIADm/RPCwVbbM
|
||||
tQOW3rsoPj01/lQ1oiAndVjDe83DXcA25fbXTFY7qtDqSbNGo/WIyR9npPSGrOdb
|
||||
vgAxvapJ41XdmJNXcJ9Q/Pdi2EV8FFRUPxjq48NQMuoDwcyPmGZ/OfuHN2ln/+8Q
|
||||
PBuzi/nEP1iA/kF3XWwEHPbrJDCmWXRBt5JDy41StlK3IP+1BJHfSq4+Z1lffhS+
|
||||
HmXDaGbejUc6AjC6P26GehwAwY9q2e/43Dgz9lsgatn+BujvnJAB5UfWDCXWIMqo
|
||||
+TndKEPEdnNiNqdm015Tgx55bRtedzGAk9ezjgiopCp/CmyUfI4P88cKEcOUilFi
|
||||
3GKjppaloUd66sgWHSNTKUqN17xkbfZMjEn90Bo+5fj1KlkeJBcesQadS9SHv9hA
|
||||
isquaduRsrRikDwqX3pil1/zWS7cYIw0VomBk0QQ78u0UMwofs5Ra0VOTLJPRl+p
|
||||
u1PUhwi76IKFkVsLaxaaAwE5wYm+VPQP+dScOSkJz6swEkDhe5A7Q61Lu3GxHM/Y
|
||||
La4WMAlE3IDOA7Piao6jI/TU5Jg65SmS7gX2
|
||||
-----END CERTIFICATE-----
|
17
mTLS/csr/wstunnel-client-1.csr.pem
Normal file
17
mTLS/csr/wstunnel-client-1.csr.pem
Normal file
|
@ -0,0 +1,17 @@
|
|||
-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIICqzCCAZMCAQAwZjELMAkGA1UEBhMCR0IxEDAOBgNVBAgMB0VuZ2xhbmQxHTAb
|
||||
BgNVBAoMFHdzdHVubmVsIGRldmVsb3BtZW50MSYwJAYDVQQDDB13c3R1bm5lbCBE
|
||||
ZXZlbG9wbWVudCBDbGllbnQgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
|
||||
ggEBAMI87ijKk6jMWPcJtkcK0AKQ5rbrkLMACkCliB4v11gikMbqMIT8eQHEfKmT
|
||||
u5uuisutMNrPqZQXCXgoYbUk0IuRuzXtmuZSMAzA5X/xWAU4fpbXwS5vd21impE6
|
||||
UZkXGQunngD5WNEn4sm7t4g/ioCTqMdv+svBMTaWXUIwpgEOKtMsaC9FVQxYe9zy
|
||||
JPN0QaSU6NMOM2LwQNzh51vtJyVT9lCixTQWM1Q5bTbQrVrzMdRZHEX6ogEg/WPU
|
||||
TaO1y+InBAVn6DzcLwslLPV7s4/6l6hmNEkZWBqz77KFc5H1Ol7PRInYLt8BlACb
|
||||
1MIlE81RYLIW1THMN7G4eVRrgq8CAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQAW
|
||||
OnKLj8cAGS568iF30bcVZHXdM99pwtXXwu/KCNCEH2XzVQAq1LmT1mpxOui+HO4e
|
||||
k8PcOqSfw14V4sDxgGuDugPysb68Dpml4zwa99MyZOr4PqJWsRLpWhXk4sRFTlQo
|
||||
yk6EE8faRg3vN/ZCR4um869Vn7pgrCky/q6e/RSsFgjRX2tNEQkHYHaSM6adA3f4
|
||||
wzKj9gHKZcE1mVmTfzfGLnPi0Y4YzqA0Zbd9rtSHVg4SX6wvJrO+bPw8CQaBh4TK
|
||||
26c11vB6S1snboi9AVN8rliYLSblZESX5txvTmjHiGV6vHnpBVceMJklgeLH2oP3
|
||||
6L9oLWpe8YewnB+d0ufb
|
||||
-----END CERTIFICATE REQUEST-----
|
17
mTLS/csr/wstunnel-server.csr.pem
Normal file
17
mTLS/csr/wstunnel-server.csr.pem
Normal file
|
@ -0,0 +1,17 @@
|
|||
-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIICqTCCAZECAQAwZDELMAkGA1UEBhMCR0IxEDAOBgNVBAgMB0VuZ2xhbmQxHTAb
|
||||
BgNVBAoMFHdzdHVubmVsIGRldmVsb3BtZW50MSQwIgYDVQQDDBt3c3R1bm5lbCBE
|
||||
ZXZlbG9wbWVudCBTZXJ2ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
|
||||
AQCukQ8xc1LHj+NxSGK714s3jMBJdzuaPsUh5tVj5I+2SMNft6SmLxRm14meUCho
|
||||
iyIaZ5K3Nd8F8+PzF2CmdH6dTY+XzZv2b0Ap544qNJ2trHwiJ9AR8zYOoCnHnlc4
|
||||
p7NatQsSJ8HozhVuPSBA46xtTUsHUFSVZt0kfGBDDXDtsnU1e3BWqvjyndvqSF/T
|
||||
F1YX1CakuY+rNKKyVUOYHE/dncMdlBA+G09NiDYhrSybiadWOU3D++oJmOFC32Mz
|
||||
2r/sMTqmHgb/NoNA83br5I8AUmhFcZTNE5pbjLgbukQrlA1snoTCNCHK39YvuC/D
|
||||
GFONWiwQdMCITn3S7z9k4/ObAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAQEAdSKi
|
||||
gdQSKSl9rXQH5FqpQgjHc9iOjQCf4JQ2cm/w+JyhS1aMtGFPaCcRc/D5rAc/3lkO
|
||||
jL+i4fS3TSo+2bfO8geU+WUNnHU18QYf9CwENsSi9lCKV1d+mTSn2H1oA+ThJKjR
|
||||
DnqzPA8AGUd9dM0dAAxPZL5A8w/IzzcK4LVEGEmiIzcVEPWjBPvSY4DQOyA2y4h/
|
||||
WL2nsG/2AD7CIFLI03bvSaTmnbQ2KSWTaSXaj5uFobJwajRLMcuCjshgdhD0C4aT
|
||||
+vlzm1gc+VbSwsyKxbmWjCLagM+BBxySLJfq9GsoXRl9QCuyd+h94rrWMeXdleZU
|
||||
fPs6uUYg2nqbyr7Vuw==
|
||||
-----END CERTIFICATE REQUEST-----
|
2
mTLS/index.txt
Normal file
2
mTLS/index.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
V 250429063902Z 1000 unknown /C=GB/ST=England/O=wstunnel development/CN=wstunnel Development Server
|
||||
V 250429064001Z 1001 unknown /C=GB/ST=England/O=wstunnel development/CN=wstunnel Development Client 1
|
1
mTLS/index.txt.attr
Normal file
1
mTLS/index.txt.attr
Normal file
|
@ -0,0 +1 @@
|
|||
unique_subject = yes
|
32
mTLS/newcerts/1000.pem
Normal file
32
mTLS/newcerts/1000.pem
Normal file
|
@ -0,0 +1,32 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIFhzCCA2+gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCR0Ix
|
||||
EDAOBgNVBAgMB0VuZ2xhbmQxHTAbBgNVBAoMFHdzdHVubmVsIGRldmVsb3BtZW50
|
||||
MSUwIwYDVQQDDBx3c3R1bm5lbCBEZXZlbG9wbWVudCBSb290IENBMB4XDTI0MDQx
|
||||
OTA2MzkwMloXDTI1MDQyOTA2MzkwMlowZDELMAkGA1UEBhMCR0IxEDAOBgNVBAgM
|
||||
B0VuZ2xhbmQxHTAbBgNVBAoMFHdzdHVubmVsIGRldmVsb3BtZW50MSQwIgYDVQQD
|
||||
DBt3c3R1bm5lbCBEZXZlbG9wbWVudCBTZXJ2ZXIwggEiMA0GCSqGSIb3DQEBAQUA
|
||||
A4IBDwAwggEKAoIBAQCukQ8xc1LHj+NxSGK714s3jMBJdzuaPsUh5tVj5I+2SMNf
|
||||
t6SmLxRm14meUChoiyIaZ5K3Nd8F8+PzF2CmdH6dTY+XzZv2b0Ap544qNJ2trHwi
|
||||
J9AR8zYOoCnHnlc4p7NatQsSJ8HozhVuPSBA46xtTUsHUFSVZt0kfGBDDXDtsnU1
|
||||
e3BWqvjyndvqSF/TF1YX1CakuY+rNKKyVUOYHE/dncMdlBA+G09NiDYhrSybiadW
|
||||
OU3D++oJmOFC32Mz2r/sMTqmHgb/NoNA83br5I8AUmhFcZTNE5pbjLgbukQrlA1s
|
||||
noTCNCHK39YvuC/DGFONWiwQdMCITn3S7z9k4/ObAgMBAAGjggFAMIIBPDAJBgNV
|
||||
HRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIGQDAzBglghkgBhvhCAQ0EJhYkT3BlblNT
|
||||
TCBHZW5lcmF0ZWQgU2VydmVyIENlcnRpZmljYXRlMB0GA1UdDgQWBBTevpkP7cSW
|
||||
XnmhdtxQej4tBVMd1DCBogYDVR0jBIGaMIGXgBTtbfEPPuXC2O2AOHxRPWgCoo07
|
||||
w6FppGcwZTELMAkGA1UEBhMCR0IxEDAOBgNVBAgMB0VuZ2xhbmQxHTAbBgNVBAoM
|
||||
FHdzdHVubmVsIGRldmVsb3BtZW50MSUwIwYDVQQDDBx3c3R1bm5lbCBEZXZlbG9w
|
||||
bWVudCBSb290IENBghRNOEar2B6EMORpy15L+8cSdEUR2zAOBgNVHQ8BAf8EBAMC
|
||||
BaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggIBABztA4Vm
|
||||
ROMZmtMmcjxV5hsNXs1iB50MBjjMvsLS2bVSfqRiENDnSrwHrGtvvcaX2sLrKtld
|
||||
Xv+zgIMU7n4UxAIPiJa+X47+glyQZXpK7MNpzQgsCtNCUyI6flqIADm/RPCwVbbM
|
||||
tQOW3rsoPj01/lQ1oiAndVjDe83DXcA25fbXTFY7qtDqSbNGo/WIyR9npPSGrOdb
|
||||
vgAxvapJ41XdmJNXcJ9Q/Pdi2EV8FFRUPxjq48NQMuoDwcyPmGZ/OfuHN2ln/+8Q
|
||||
PBuzi/nEP1iA/kF3XWwEHPbrJDCmWXRBt5JDy41StlK3IP+1BJHfSq4+Z1lffhS+
|
||||
HmXDaGbejUc6AjC6P26GehwAwY9q2e/43Dgz9lsgatn+BujvnJAB5UfWDCXWIMqo
|
||||
+TndKEPEdnNiNqdm015Tgx55bRtedzGAk9ezjgiopCp/CmyUfI4P88cKEcOUilFi
|
||||
3GKjppaloUd66sgWHSNTKUqN17xkbfZMjEn90Bo+5fj1KlkeJBcesQadS9SHv9hA
|
||||
isquaduRsrRikDwqX3pil1/zWS7cYIw0VomBk0QQ78u0UMwofs5Ra0VOTLJPRl+p
|
||||
u1PUhwi76IKFkVsLaxaaAwE5wYm+VPQP+dScOSkJz6swEkDhe5A7Q61Lu3GxHM/Y
|
||||
La4WMAlE3IDOA7Piao6jI/TU5Jg65SmS7gX2
|
||||
-----END CERTIFICATE-----
|
30
mTLS/newcerts/1001.pem
Normal file
30
mTLS/newcerts/1001.pem
Normal file
|
@ -0,0 +1,30 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIFDTCCAvWgAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCR0Ix
|
||||
EDAOBgNVBAgMB0VuZ2xhbmQxHTAbBgNVBAoMFHdzdHVubmVsIGRldmVsb3BtZW50
|
||||
MSUwIwYDVQQDDBx3c3R1bm5lbCBEZXZlbG9wbWVudCBSb290IENBMB4XDTI0MDQx
|
||||
OTA2NDAwMVoXDTI1MDQyOTA2NDAwMVowZjELMAkGA1UEBhMCR0IxEDAOBgNVBAgM
|
||||
B0VuZ2xhbmQxHTAbBgNVBAoMFHdzdHVubmVsIGRldmVsb3BtZW50MSYwJAYDVQQD
|
||||
DB13c3R1bm5lbCBEZXZlbG9wbWVudCBDbGllbnQgMTCCASIwDQYJKoZIhvcNAQEB
|
||||
BQADggEPADCCAQoCggEBAMI87ijKk6jMWPcJtkcK0AKQ5rbrkLMACkCliB4v11gi
|
||||
kMbqMIT8eQHEfKmTu5uuisutMNrPqZQXCXgoYbUk0IuRuzXtmuZSMAzA5X/xWAU4
|
||||
fpbXwS5vd21impE6UZkXGQunngD5WNEn4sm7t4g/ioCTqMdv+svBMTaWXUIwpgEO
|
||||
KtMsaC9FVQxYe9zyJPN0QaSU6NMOM2LwQNzh51vtJyVT9lCixTQWM1Q5bTbQrVrz
|
||||
MdRZHEX6ogEg/WPUTaO1y+InBAVn6DzcLwslLPV7s4/6l6hmNEkZWBqz77KFc5H1
|
||||
Ol7PRInYLt8BlACb1MIlE81RYLIW1THMN7G4eVRrgq8CAwEAAaOBxTCBwjAJBgNV
|
||||
HRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIFoDAzBglghkgBhvhCAQ0EJhYkT3BlblNT
|
||||
TCBHZW5lcmF0ZWQgQ2xpZW50IENlcnRpZmljYXRlMB0GA1UdDgQWBBS3UAwJmyci
|
||||
WunqYPI4DSNTMjpBIjAfBgNVHSMEGDAWgBTtbfEPPuXC2O2AOHxRPWgCoo07wzAO
|
||||
BgNVHQ8BAf8EBAMCBeAwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMA0G
|
||||
CSqGSIb3DQEBCwUAA4ICAQCyUuIIIylwAEJ0x4cvwuuV65MnsDiNktpqllsih/wo
|
||||
bfutcvGy//FOMk/04YYJZbLAOfvNLakp3A+oEGOuYaMJst9e2zGXRI2AqPZzxxkY
|
||||
P1GAfnxiLtjHltUMlpMrx+thGWqKYYAXim8TY3O3hjXkrpE8vOTG5vpQmMMmo2/y
|
||||
Po++eiVbd/+cXDdMwbum31rexpN0JC9SBF9GmrHoKekPpQ+gGJe6HAVAEWV2UMId
|
||||
MEtKzk8RrwySfn6oErNkOD+4DF9eJogl2cjlfl5y+DHeadAtYDcXS8lEvgJ6LwsE
|
||||
ftDMhtY1FBrq5nCxip2Fk6uB08wypcHXC/+sXP71tCBuQiaHCW/GTaFlWQijfepq
|
||||
yh/zx9narIxpTFCVfX1hiy6uYkehvWiBsds0LNwVzSUEC+wfxuwGlVWRtalf/K9e
|
||||
+1CHraMP0VjsSO+U5CWKuNdPffq/V/v2nyKzkbakssZex3Xoy0sWZ/i0tl2AD+K8
|
||||
p9SRRuWShv2q3qZUfbKRgGnIlsCJNK3xUlak6HTPpL/woV3QfakO81E06x/Mlgvm
|
||||
9PXA9t0yp+hyk0S9mgwAiL5/s6pm+A0WsSjJ6ohl2jsktvAYgFy7S/rFL7ZC7kN1
|
||||
TH+dlY/0Cj5yBlA0G0B2VEoW0nrnUGfA6xxnl1Tv096bhxCUKg9YC+/VDRgIVyX4
|
||||
uw==
|
||||
-----END CERTIFICATE-----
|
99
mTLS/openssl.cnf
Normal file
99
mTLS/openssl.cnf
Normal file
|
@ -0,0 +1,99 @@
|
|||
[ ca ]
|
||||
default_ca = CA_default
|
||||
|
||||
[ CA_default ]
|
||||
# Directory and file locations.
|
||||
dir = /home/erebe/progs/wstunnel/certs/mTLS
|
||||
certs = $dir/certs
|
||||
crl_dir = $dir/crl
|
||||
new_certs_dir = $dir/newcerts
|
||||
database = $dir/index.txt
|
||||
serial = $dir/serial
|
||||
RANDFILE = $dir/private/.rand
|
||||
|
||||
# The root key and root certificate.
|
||||
private_key = $dir/private/ca.key.pem
|
||||
certificate = $dir/certs/ca.cert.pem
|
||||
|
||||
# For certificate revocation lists.
|
||||
crlnumber = $dir/crlnumber
|
||||
crl = $dir/crl/ca.crl.pem
|
||||
crl_extensions = crl_ext
|
||||
default_crl_days = 30
|
||||
|
||||
# SHA-1 is deprecated, so use SHA-2 instead.
|
||||
default_md = sha256
|
||||
|
||||
name_opt = ca_default
|
||||
cert_opt = ca_default
|
||||
default_days = 375
|
||||
preserve = no
|
||||
policy = policy_loose
|
||||
|
||||
[ policy_loose ]
|
||||
countryName = optional
|
||||
stateOrProvinceName = optional
|
||||
localityName = optional
|
||||
organizationName = optional
|
||||
organizationalUnitName = optional
|
||||
commonName = supplied
|
||||
emailAddress = optional
|
||||
|
||||
[ req ]
|
||||
# Configuration for a certificate signing request.
|
||||
default_bits = 2048
|
||||
distinguished_name = req_distinguished_name
|
||||
string_mask = utf8only
|
||||
# SHA-1 is deprecated, so use SHA-2 instead.
|
||||
default_md = sha256
|
||||
# Extension to add when the -x509 option is used.
|
||||
x509_extensions = v3_ca
|
||||
|
||||
[ req_distinguished_name ]
|
||||
# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
|
||||
countryName = Country Name (2 letter code)
|
||||
stateOrProvinceName = State or Province Name
|
||||
localityName = Locality Name
|
||||
0.organizationName = Organization Name
|
||||
organizationalUnitName = Organizational Unit Name
|
||||
commonName = Common Name
|
||||
emailAddress = Email Address
|
||||
|
||||
# Optionally, specify some defaults.
|
||||
countryName_default = GB
|
||||
stateOrProvinceName_default = England
|
||||
localityName_default =
|
||||
0.organizationName_default = wstunnel development
|
||||
#organizationalUnitName_default =
|
||||
#emailAddress_default =
|
||||
|
||||
[ v3_ca ]
|
||||
# Configuration for a certificate authority.
|
||||
subjectKeyIdentifier = hash
|
||||
authorityKeyIdentifier = keyid:always,issuer
|
||||
basicConstraints = critical, CA:true
|
||||
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
|
||||
|
||||
[ client_cert ]
|
||||
# Configuration for client certificates.
|
||||
basicConstraints = CA:FALSE
|
||||
nsCertType = client, email
|
||||
nsComment = "OpenSSL Generated Client Certificate"
|
||||
subjectKeyIdentifier = hash
|
||||
authorityKeyIdentifier = keyid,issuer
|
||||
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
|
||||
extendedKeyUsage = clientAuth, emailProtection
|
||||
|
||||
[ server_cert ]
|
||||
# Configuration for server certificates.
|
||||
basicConstraints = CA:FALSE
|
||||
nsCertType = server
|
||||
nsComment = "OpenSSL Generated Server Certificate"
|
||||
subjectKeyIdentifier = hash
|
||||
authorityKeyIdentifier = keyid,issuer:always
|
||||
keyUsage = critical, digitalSignature, keyEncipherment
|
||||
extendedKeyUsage = serverAuth
|
||||
|
||||
[ crl_ext ]
|
||||
# Configuration for CRLs.
|
||||
authorityKeyIdentifier=keyid:always
|
52
mTLS/private/ca.key.pem
Normal file
52
mTLS/private/ca.key.pem
Normal file
|
@ -0,0 +1,52 @@
|
|||
-----BEGIN PRIVATE KEY-----
|
||||
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
|
||||
d9HqBI2AwjW8MYtrV4UaM2bM6n7aow==
|
||||
-----END PRIVATE KEY-----
|
28
mTLS/private/wstunnel-client-1.pem
Normal file
28
mTLS/private/wstunnel-client-1.pem
Normal file
|
@ -0,0 +1,28 @@
|
|||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDCPO4oypOozFj3
|
||||
CbZHCtACkOa265CzAApApYgeL9dYIpDG6jCE/HkBxHypk7ubrorLrTDaz6mUFwl4
|
||||
KGG1JNCLkbs17ZrmUjAMwOV/8VgFOH6W18Eub3dtYpqROlGZFxkLp54A+VjRJ+LJ
|
||||
u7eIP4qAk6jHb/rLwTE2ll1CMKYBDirTLGgvRVUMWHvc8iTzdEGklOjTDjNi8EDc
|
||||
4edb7SclU/ZQosU0FjNUOW020K1a8zHUWRxF+qIBIP1j1E2jtcviJwQFZ+g83C8L
|
||||
JSz1e7OP+peoZjRJGVgas++yhXOR9Tpez0SJ2C7fAZQAm9TCJRPNUWCyFtUxzDex
|
||||
uHlUa4KvAgMBAAECggEAPWP3nAHm6IdpqO6zY0HKG72DhhXu/nxJQURwQKY7SDpo
|
||||
is4S9r07W7En+4rbVWm1qYk8MzRGMy2SyxzsQM35cdtmEbXe6uPYFvfSsXzspn3E
|
||||
GNXpU01csEBlfPgzOREhU9su57zncvfJyJvhdpkqo9fHlP1SBZsyfD/LCvQIS7WL
|
||||
IsjQeRYGeGI+T+HiJyRGqkkk0YWZ09OL8QCAwTyhT58TH+7HzoWRBCCHGQaIS/Wm
|
||||
kMcPJsYLSNtwrj2qvG7dC4nZcl3ZHoRHVGnD4B+6y0esS8cHvu67FX09FviIrz6G
|
||||
l7EnU/uWnJ8iKDwl7Jwqeu/mk06OecI6KlYokbbeZQKBgQDgC0yqdPyIU7TZtihq
|
||||
cnet9yqm20yATSODIeOc2SPchMvF/EqLgBikSOBMTbl7OsZqfeTbPLbcKXbuJKa7
|
||||
QGu+5NJM6OKWW3h+aCwaB0YSQQnNtiqEOJoMPErm9Bj4jLEdVMP1J66i9ra+gxka
|
||||
plL/cUsNxCZaUhieTHq70zlQWwKBgQDd8UvMtUdqLvAQ1oT8oX+C7hlGAdYjHXIH
|
||||
PeBz+pWZWfNdH/lijWUEKBtynzmTJpvE52M6849MamUSFk7ypTe0NZJ/oPgxC0Nl
|
||||
yAr49yZmByJ6RiKOJTexmykWVhSi6x++HmWE0oz6+2vRIQ+Wdj0VWmUP+LVsvMD0
|
||||
QjrkhIinPQKBgQCf7NDr+BfvRDkbEyEkYtM1NfKXKoEgMHACAeXUp1cm6RAAIogf
|
||||
re9pDbA2J2EYKqtJhtYe/ObWny6K7VSq42BF4laPmclsZJzNNpUMe1a0XwKdecQ9
|
||||
n52u0DbzRxiwCtW+xywdyhapswxdT31S/ZjPSFK33+U0odd638LYYf1OcwKBgQDR
|
||||
bsh7dLjeP0q0aOn3RyJ/V9UrlcIPQtL+eGpcpyMSIaqfvvNjB1BCmuJDyHLZI/6r
|
||||
0Tl3QKyBjIixh7GaEUQ+XqtOmoR6K0m/OwT3qKlob+UeAx7Kid5DT8p21GYG0t8S
|
||||
VbawnssAb85u+sat0geUJcfmSWhSIs/l7rWKPHKDdQKBgDqVTFHDncc3p4luCRgi
|
||||
63cjz1fLSn+wiiICMsYTCJ9lHDwbXOKWAqyHDP0qTI8s3b13/LITOdj/Q0R33i0Y
|
||||
38qJWBag5K2u7iyMQr/oxipuBhyhHU1mRXGXHl4/N3Oa5tkVhapz/e6PN0mMgTJQ
|
||||
/x19K09p5hc4sLnrk6BCOr3q
|
||||
-----END PRIVATE KEY-----
|
28
mTLS/private/wstunnel-server.pem
Normal file
28
mTLS/private/wstunnel-server.pem
Normal file
|
@ -0,0 +1,28 @@
|
|||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCukQ8xc1LHj+Nx
|
||||
SGK714s3jMBJdzuaPsUh5tVj5I+2SMNft6SmLxRm14meUChoiyIaZ5K3Nd8F8+Pz
|
||||
F2CmdH6dTY+XzZv2b0Ap544qNJ2trHwiJ9AR8zYOoCnHnlc4p7NatQsSJ8HozhVu
|
||||
PSBA46xtTUsHUFSVZt0kfGBDDXDtsnU1e3BWqvjyndvqSF/TF1YX1CakuY+rNKKy
|
||||
VUOYHE/dncMdlBA+G09NiDYhrSybiadWOU3D++oJmOFC32Mz2r/sMTqmHgb/NoNA
|
||||
83br5I8AUmhFcZTNE5pbjLgbukQrlA1snoTCNCHK39YvuC/DGFONWiwQdMCITn3S
|
||||
7z9k4/ObAgMBAAECggEAQgKcaiifrtLcQKQModdZz4Gr3Jv3r9X4mV8+Ze2x4k4V
|
||||
gwZgfm7jGhh686CABzhFhxKPSjRWx1t4YR3/8DGxBy6jE9YuGbvr2Wy0N4V58oh8
|
||||
0DWZ2o/LazBpXBCmDshra+t16kGac7wqImt+3Mq7EwHdU0CvG2ewS/G0PObCQz9O
|
||||
UCIitSoO/TCLBmVOVND9u9tR6VX+nmqv7lbs5s311g2OXWbFQQDaWj9ftx6nZ0w+
|
||||
k1MhXVYpKw1iM6fiaq5HB8AFF+H92bZyBGNxE3L9/peynzBnrwGb/n+w5cDSlmWI
|
||||
NsIDMslAgAJktttNXanwwWPiZTUj9/RJ0aE7Md3QEQKBgQDbsYumFBVuV3khr4pL
|
||||
fHRnAcDHRIGyWG5H/VZbNzeEZ1VVDGP1Xym0K3QtNKfM00gBIPIqnFf/gUuReY67
|
||||
H9HKg8i8kjSFH0G1HtR/dPVPqSc/DVeoEmy9hwgRH01ZYebL/fT9kRhn0bBLtoVh
|
||||
bYUSFDYxkJIT9uhZDysDbKR8JQKBgQDLalrSWG9G+PIGdKuPeMDdZHMNWSdGYECe
|
||||
Fv+oyhDQoH9228UJihIcbwT+ocsl/w0CK8Gvri8jxOnHW0yAzCaxCwi5VQWRCt1G
|
||||
rTs8O6jtDi3wBc3IdLl3ktfA8OEbOShiQh3YYMRCPBg/21A5SCyHdMEEwaF/842A
|
||||
6OxeUPPEvwKBgBwVtF6EzsCOWiPeRvWjcVYBuV0/+ryL5X06e6Gpi2VXuGbo8JZb
|
||||
lf88Vtu4kYLzt469YXflCLLXGov8WCy/wpf7BNxmbGRgPIwk5tFsaDfIzgWXdQ89
|
||||
W71W18cok0DL7S9CxeDsfYw4GCt1p9NupsZK4yqu6p22wLkx4TPM3bIpAoGAO+nE
|
||||
fGYNyIK0jpA4o9Z2P/9BH/Jdbg4Vmjq97JIvp7NON8z9WRTwxq0wdGtlMXjQ9Q28
|
||||
S6lrOwbZsJ1EiD8ZOlY8qJHRROpFSHbnlpMf60qc3zBmbx9qLTz0DWElfGY2bdJ5
|
||||
hezigXu/zLclBuoqK2+JFoSNs+khiZGRZSpE0nMCgYEAzs0oC0doQhulvZz1nPzb
|
||||
AgthFZS4gIq8GsTW0GfXRYPRHEtHtDoYROEYM2aX7FcFRAKO/9iinW19rtMj6cpS
|
||||
37tBMiEAGqInmPYGVfUalZpZKq14f85lVOg9HjTf/MxPs7RHgKj4WD1r4aeAhxPz
|
||||
d1+I0rsmh2lceuhHer/sS4M=
|
||||
-----END PRIVATE KEY-----
|
1
mTLS/serial
Normal file
1
mTLS/serial
Normal file
|
@ -0,0 +1 @@
|
|||
1002
|
104
src/main.rs
104
src/main.rs
|
@ -19,7 +19,7 @@ use hyper::header::HOST;
|
|||
use hyper::http::{HeaderName, HeaderValue};
|
||||
use log::{debug, warn};
|
||||
use once_cell::sync::Lazy;
|
||||
use parking_lot::Mutex;
|
||||
use parking_lot::{Mutex, RwLock};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::fmt::{Debug, Formatter};
|
||||
|
@ -40,6 +40,7 @@ use tokio_rustls::TlsConnector;
|
|||
use tracing::{error, info};
|
||||
|
||||
use crate::dns::DnsResolver;
|
||||
use crate::tunnel::tls_reloader::TlsReloader;
|
||||
use crate::tunnel::{to_host_port, RemoteAddr, TransportAddr, TransportScheme};
|
||||
use crate::udp::MyUdpSocket;
|
||||
use tracing_subscriber::filter::Directive;
|
||||
|
@ -60,7 +61,7 @@ struct Wstunnel {
|
|||
|
||||
/// *WARNING* The flag does nothing, you need to set the env variable *WARNING*
|
||||
/// Control the number of threads that will be used.
|
||||
/// By default it is equal the number of cpus
|
||||
/// By default, it is equal the number of cpus
|
||||
#[arg(
|
||||
long,
|
||||
global = true,
|
||||
|
@ -132,7 +133,7 @@ struct Client {
|
|||
#[arg(short = 'c', long, value_name = "INT", default_value = "0", verbatim_doc_comment)]
|
||||
connection_min_idle: u32,
|
||||
|
||||
/// Domain name that will be use as SNI during TLS handshake
|
||||
/// Domain name that will be used as SNI during TLS handshake
|
||||
/// Warning: If you are behind a CDN (i.e: Cloudflare) you must set this domain also in the http HOST header.
|
||||
/// or it will be flagged as fishy and your request rejected
|
||||
#[arg(long, value_name = "DOMAIN_NAME", value_parser = parse_sni_override, verbatim_doc_comment)]
|
||||
|
@ -144,7 +145,7 @@ struct Client {
|
|||
tls_sni_disable: bool,
|
||||
|
||||
/// Enable TLS certificate verification.
|
||||
/// Disabled by default. The client will happily connect to any server with self signed certificate.
|
||||
/// Disabled by default. The client will happily connect to any server with self-signed certificate.
|
||||
#[arg(long, verbatim_doc_comment)]
|
||||
tls_verify_certificate: bool,
|
||||
|
||||
|
@ -192,7 +193,7 @@ struct Client {
|
|||
websocket_ping_frequency_sec: Option<Duration>,
|
||||
|
||||
/// Enable the masking of websocket frames. Default is false
|
||||
/// Enable this option only if you use unsecure (non TLS) websocket server and you see some issues. Otherwise, it is just overhead.
|
||||
/// Enable this option only if you use unsecure (non TLS) websocket server, and you see some issues. Otherwise, it is just overhead.
|
||||
#[arg(long, default_value = "false", verbatim_doc_comment)]
|
||||
websocket_mask_frame: bool,
|
||||
|
||||
|
@ -203,7 +204,7 @@ struct Client {
|
|||
|
||||
/// Send custom headers in the upgrade request reading them from a file.
|
||||
/// It overrides http_headers specified from command line.
|
||||
/// File is read everytime and file format must contains lines with `HEADER_NAME: HEADER_VALUE`
|
||||
/// File is read everytime and file format must contain lines with `HEADER_NAME: HEADER_VALUE`
|
||||
#[arg(long, value_name = "FILE_PATH", verbatim_doc_comment)]
|
||||
http_headers_file: Option<PathBuf>,
|
||||
|
||||
|
@ -220,6 +221,17 @@ struct Client {
|
|||
/// The only way to make it works with http2 is to have wstunnel directly exposed to the internet without any reverse proxy in front of it
|
||||
#[arg(value_name = "ws[s]|http[s]://wstunnel.server.com[:port]", value_parser = parse_server_url, verbatim_doc_comment)]
|
||||
remote_addr: Url,
|
||||
|
||||
/// [Optional] Certificate (pem) to present to the server when connecting over TLS (HTTPS).
|
||||
/// Used when the server requires clients to authenticate themselves with a certificate (i.e. mTLS).
|
||||
/// The certificate will be automatically reloaded if it changes
|
||||
#[arg(long, value_name = "FILE_PATH", verbatim_doc_comment)]
|
||||
tls_certificate: Option<PathBuf>,
|
||||
|
||||
/// [Optional] The private key for the corresponding certificate used with mTLS.
|
||||
/// The certificate will be automatically reloaded if it changes
|
||||
#[arg(long, value_name = "FILE_PATH", verbatim_doc_comment)]
|
||||
tls_private_key: Option<PathBuf>,
|
||||
}
|
||||
|
||||
#[derive(clap::Args, Debug)]
|
||||
|
@ -241,7 +253,7 @@ struct Server {
|
|||
websocket_ping_frequency_sec: Option<Duration>,
|
||||
|
||||
/// Enable the masking of websocket frames. Default is false
|
||||
/// Enable this option only if you use unsecure (non TLS) websocket server and you see some issues. Otherwise, it is just overhead.
|
||||
/// Enable this option only if you use unsecure (non TLS) websocket server, and you see some issues. Otherwise, it is just overhead.
|
||||
#[arg(long, default_value = "false", verbatim_doc_comment)]
|
||||
websocket_mask_frame: bool,
|
||||
|
||||
|
@ -264,7 +276,7 @@ struct Server {
|
|||
dns_resolver: Option<Vec<Url>>,
|
||||
|
||||
/// Server will only accept connection from if this specific path prefix is used during websocket upgrade.
|
||||
/// Useful if you specify in the client a custom path prefix and you want the server to only allow this one.
|
||||
/// Useful if you specify in the client a custom path prefix, and you want the server to only allow this one.
|
||||
/// The path prefix act as a secret to authenticate clients
|
||||
/// Disabled by default. Accept all path prefix. Can be specified multiple time
|
||||
#[arg(
|
||||
|
@ -275,7 +287,7 @@ struct Server {
|
|||
)]
|
||||
restrict_http_upgrade_path_prefix: Option<Vec<String>>,
|
||||
|
||||
/// [Optional] Use custom certificate (pem) instead of the default embedded self signed certificate.
|
||||
/// [Optional] Use custom certificate (pem) instead of the default embedded self-signed certificate.
|
||||
/// The certificate will be automatically reloaded if it changes
|
||||
#[arg(long, value_name = "FILE_PATH", verbatim_doc_comment)]
|
||||
tls_certificate: Option<PathBuf>,
|
||||
|
@ -284,6 +296,12 @@ struct Server {
|
|||
/// The private key will be automatically reloaded if it changes
|
||||
#[arg(long, value_name = "FILE_PATH", verbatim_doc_comment)]
|
||||
tls_private_key: Option<PathBuf>,
|
||||
|
||||
/// [Optional] Enables mTLS (client authentication with certificate). Argument must be PEM file
|
||||
/// containing one or more certificates of CA's of which the certificate of clients needs to be signed with.
|
||||
/// The ca will be automatically reloaded if it changes
|
||||
#[arg(long, value_name = "FILE_PATH", verbatim_doc_comment)]
|
||||
tls_client_ca_certs: Option<PathBuf>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
||||
|
@ -565,15 +583,25 @@ pub struct TlsClientConfig {
|
|||
pub tls_sni_disabled: bool,
|
||||
pub tls_sni_override: Option<DnsName>,
|
||||
pub tls_verify_certificate: bool,
|
||||
pub tls_connector: TlsConnector,
|
||||
tls_connector: Arc<RwLock<TlsConnector>>,
|
||||
pub tls_certificate_path: Option<PathBuf>,
|
||||
pub tls_key_path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl TlsClientConfig {
|
||||
pub fn tls_connector(&self) -> TlsConnector {
|
||||
self.tls_connector.read().clone()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TlsServerConfig {
|
||||
pub tls_certificate: Mutex<Vec<Certificate>>,
|
||||
pub tls_key: Mutex<PrivateKey>,
|
||||
pub tls_client_ca_certificates: Option<Mutex<Vec<Certificate>>>,
|
||||
pub tls_certificate_path: Option<PathBuf>,
|
||||
pub tls_key_path: Option<PathBuf>,
|
||||
pub tls_client_ca_certs_path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
pub struct WsServerConfig {
|
||||
|
@ -599,6 +627,14 @@ impl Debug for WsServerConfig {
|
|||
.field("timeout_connect", &self.timeout_connect)
|
||||
.field("websocket_mask_frame", &self.websocket_mask_frame)
|
||||
.field("tls", &self.tls.is_some())
|
||||
.field(
|
||||
"mTLS",
|
||||
&self
|
||||
.tls
|
||||
.as_ref()
|
||||
.map(|x| x.tls_client_ca_certificates.is_some())
|
||||
.unwrap_or(false),
|
||||
)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
@ -617,6 +653,7 @@ pub struct WsClientConfig {
|
|||
pub websocket_mask_frame: bool,
|
||||
pub http_proxy: Option<Url>,
|
||||
cnx_pool: Option<bb8::Pool<WsClientConfig>>,
|
||||
tls_reloader: Option<Arc<TlsReloader>>,
|
||||
pub dns_resolver: DnsResolver,
|
||||
}
|
||||
|
||||
|
@ -682,30 +719,54 @@ async fn main() {
|
|||
|
||||
match args.commands {
|
||||
Commands::Client(args) => {
|
||||
let tls = match TransportScheme::from_str(args.remote_addr.scheme()).expect("invalid scheme in server url")
|
||||
let (tls_certificate, tls_key) = if let (Some(cert), Some(key)) =
|
||||
(args.tls_certificate.as_ref(), args.tls_private_key.as_ref())
|
||||
{
|
||||
let tls_certificate =
|
||||
tls::load_certificates_from_pem(cert).expect("Cannot load client TLS certificate (mTLS)");
|
||||
let tls_key = tls::load_private_key_from_file(key).expect("Cannot load client TLS private key (mTLS)");
|
||||
(Some(tls_certificate), Some(tls_key))
|
||||
} else {
|
||||
(None, None)
|
||||
};
|
||||
|
||||
let transport_scheme =
|
||||
TransportScheme::from_str(args.remote_addr.scheme()).expect("invalid scheme in server url");
|
||||
let tls = match transport_scheme {
|
||||
TransportScheme::Ws | TransportScheme::Http => None,
|
||||
TransportScheme::Wss => Some(TlsClientConfig {
|
||||
tls_connector: tls::tls_connector(
|
||||
tls_connector: Arc::new(RwLock::new(
|
||||
tls::tls_connector(
|
||||
args.tls_verify_certificate,
|
||||
Some(vec![b"http/1.1".to_vec()]),
|
||||
transport_scheme.alpn_protocols(),
|
||||
!args.tls_sni_disable,
|
||||
tls_certificate,
|
||||
tls_key,
|
||||
)
|
||||
.expect("Cannot create tls connector"),
|
||||
)),
|
||||
tls_sni_override: args.tls_sni_override,
|
||||
tls_verify_certificate: args.tls_verify_certificate,
|
||||
tls_sni_disabled: args.tls_sni_disable,
|
||||
tls_certificate_path: args.tls_certificate.clone(),
|
||||
tls_key_path: args.tls_private_key.clone(),
|
||||
}),
|
||||
TransportScheme::Https => Some(TlsClientConfig {
|
||||
tls_connector: tls::tls_connector(
|
||||
tls_connector: Arc::new(RwLock::new(
|
||||
tls::tls_connector(
|
||||
args.tls_verify_certificate,
|
||||
Some(vec![b"h2".to_vec()]),
|
||||
transport_scheme.alpn_protocols(),
|
||||
!args.tls_sni_disable,
|
||||
tls_certificate,
|
||||
tls_key,
|
||||
)
|
||||
.expect("Cannot create tls connector"),
|
||||
)),
|
||||
tls_sni_override: args.tls_sni_override,
|
||||
tls_verify_certificate: args.tls_verify_certificate,
|
||||
tls_sni_disabled: args.tls_sni_disable,
|
||||
tls_certificate_path: args.tls_certificate.clone(),
|
||||
tls_key_path: args.tls_private_key.clone(),
|
||||
}),
|
||||
};
|
||||
|
||||
|
@ -761,6 +822,7 @@ async fn main() {
|
|||
None
|
||||
},
|
||||
cnx_pool: None,
|
||||
tls_reloader: None,
|
||||
dns_resolver: if let Ok(resolver) = hickory_resolver::AsyncResolver::tokio_from_system_conf() {
|
||||
DnsResolver::TrustDns(resolver)
|
||||
} else {
|
||||
|
@ -769,6 +831,9 @@ async fn main() {
|
|||
},
|
||||
};
|
||||
|
||||
let tls_reloader =
|
||||
TlsReloader::new_for_client(Arc::new(client_config.clone())).expect("Cannot create tls reloader");
|
||||
client_config.tls_reloader = Some(Arc::new(tls_reloader));
|
||||
let pool = bb8::Pool::builder()
|
||||
.max_size(1000)
|
||||
.min_idle(Some(args.connection_min_idle))
|
||||
|
@ -1120,11 +1185,20 @@ async fn main() {
|
|||
embedded_certificate::TLS_PRIVATE_KEY.clone()
|
||||
};
|
||||
|
||||
let tls_client_ca_certificates = args.tls_client_ca_certs.as_ref().map(|tls_client_ca| {
|
||||
Mutex::new(
|
||||
tls::load_certificates_from_pem(tls_client_ca)
|
||||
.expect("Cannot load client CA certificate (mTLS)"),
|
||||
)
|
||||
});
|
||||
|
||||
Some(TlsServerConfig {
|
||||
tls_certificate: Mutex::new(tls_certificate),
|
||||
tls_key: Mutex::new(tls_key),
|
||||
tls_client_ca_certificates,
|
||||
tls_certificate_path: args.tls_certificate,
|
||||
tls_key_path: args.tls_private_key,
|
||||
tls_client_ca_certs_path: args.tls_client_ca_certs,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
|
|
38
src/tls.rs
38
src/tls.rs
|
@ -12,6 +12,7 @@ use tokio_rustls::client::TlsStream;
|
|||
use tokio_rustls::rustls::client::{ServerCertVerified, ServerCertVerifier};
|
||||
|
||||
use crate::tunnel::TransportAddr;
|
||||
use tokio_rustls::rustls::server::{AllowAnyAuthenticatedClient, NoClientAuth};
|
||||
use tokio_rustls::rustls::{Certificate, ClientConfig, KeyLogFile, PrivateKey, ServerName};
|
||||
use tokio_rustls::{rustls, TlsAcceptor, TlsConnector};
|
||||
use tracing::info;
|
||||
|
@ -65,8 +66,10 @@ pub fn load_private_key_from_file(path: &Path) -> anyhow::Result<PrivateKey> {
|
|||
|
||||
pub fn tls_connector(
|
||||
tls_verify_certificate: bool,
|
||||
alpn_protocols: Option<Vec<Vec<u8>>>,
|
||||
alpn_protocols: Vec<Vec<u8>>,
|
||||
enable_sni: bool,
|
||||
tls_client_certificate: Option<Vec<Certificate>>,
|
||||
tls_client_key: Option<PrivateKey>,
|
||||
) -> anyhow::Result<TlsConnector> {
|
||||
let mut root_store = rustls::RootCertStore::empty();
|
||||
|
||||
|
@ -79,10 +82,16 @@ pub fn tls_connector(
|
|||
}
|
||||
}
|
||||
|
||||
let mut config = ClientConfig::builder()
|
||||
let config_builder = ClientConfig::builder()
|
||||
.with_safe_defaults()
|
||||
.with_root_certificates(root_store)
|
||||
.with_no_client_auth();
|
||||
.with_root_certificates(root_store);
|
||||
|
||||
let mut config = match (tls_client_certificate, tls_client_key) {
|
||||
(Some(tls_client_certificate), Some(tls_client_key)) => config_builder
|
||||
.with_client_auth_cert(tls_client_certificate, tls_client_key)
|
||||
.with_context(|| "Error setting up mTLS")?,
|
||||
_ => config_builder.with_no_client_auth(),
|
||||
};
|
||||
|
||||
config.enable_sni = enable_sni;
|
||||
config.key_log = Arc::new(KeyLogFile::new());
|
||||
|
@ -92,17 +101,28 @@ pub fn tls_connector(
|
|||
config.dangerous().set_certificate_verifier(Arc::new(NullVerifier));
|
||||
}
|
||||
|
||||
if let Some(alpn_protocols) = alpn_protocols {
|
||||
config.alpn_protocols = alpn_protocols;
|
||||
}
|
||||
let tls_connector = TlsConnector::from(Arc::new(config));
|
||||
Ok(tls_connector)
|
||||
}
|
||||
|
||||
pub fn tls_acceptor(tls_cfg: &TlsServerConfig, alpn_protocols: Option<Vec<Vec<u8>>>) -> anyhow::Result<TlsAcceptor> {
|
||||
let client_cert_verifier = if let Some(tls_client_ca_certificates) = &tls_cfg.tls_client_ca_certificates {
|
||||
let mut root_store = rustls::RootCertStore::empty();
|
||||
for tls_client_ca_certificate in tls_client_ca_certificates.lock().iter() {
|
||||
root_store
|
||||
.add(tls_client_ca_certificate)
|
||||
.with_context(|| "Failed to add mTLS client CA certificate")?;
|
||||
}
|
||||
|
||||
Arc::new(AllowAnyAuthenticatedClient::new(root_store))
|
||||
} else {
|
||||
NoClientAuth::boxed()
|
||||
};
|
||||
|
||||
let mut config = rustls::ServerConfig::builder()
|
||||
.with_safe_defaults()
|
||||
.with_no_client_auth()
|
||||
.with_client_cert_verifier(client_cert_verifier)
|
||||
.with_single_cert(tls_cfg.tls_certificate.lock().clone(), tls_cfg.tls_key.lock().clone())
|
||||
.with_context(|| "invalid tls certificate or private key")?;
|
||||
|
||||
|
@ -116,8 +136,8 @@ pub fn tls_acceptor(tls_cfg: &TlsServerConfig, alpn_protocols: Option<Vec<Vec<u8
|
|||
pub async fn connect(client_cfg: &WsClientConfig, tcp_stream: TcpStream) -> anyhow::Result<TlsStream<TcpStream>> {
|
||||
let sni = client_cfg.tls_server_name();
|
||||
let (tls_connector, sni_disabled) = match &client_cfg.remote_addr {
|
||||
TransportAddr::Wss { tls, .. } => (&tls.tls_connector, tls.tls_sni_disabled),
|
||||
TransportAddr::Https { tls, .. } => (&tls.tls_connector, tls.tls_sni_disabled),
|
||||
TransportAddr::Wss { tls, .. } => (tls.tls_connector(), tls.tls_sni_disabled),
|
||||
TransportAddr::Https { tls, .. } => (tls.tls_connector(), tls.tls_sni_disabled),
|
||||
TransportAddr::Http { .. } | TransportAddr::Ws { .. } => {
|
||||
return Err(anyhow!("Transport does not support TLS: {}", client_cfg.remote_addr.scheme()))
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
pub mod client;
|
||||
pub mod server;
|
||||
mod tls_reloader;
|
||||
pub mod tls_reloader;
|
||||
mod transport;
|
||||
|
||||
use crate::{tcp, tls, LocalProtocol, TlsClientConfig, WsClientConfig};
|
||||
|
@ -104,6 +104,15 @@ impl TransportScheme {
|
|||
TransportScheme::Https => "https",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn alpn_protocols(&self) -> Vec<Vec<u8>> {
|
||||
match self {
|
||||
TransportScheme::Ws => vec![],
|
||||
TransportScheme::Wss => vec![b"http/1.1".to_vec()],
|
||||
TransportScheme::Http => vec![],
|
||||
TransportScheme::Https => vec![b"h2".to_vec()],
|
||||
}
|
||||
}
|
||||
}
|
||||
impl FromStr for TransportScheme {
|
||||
type Err = ();
|
||||
|
|
|
@ -597,7 +597,7 @@ pub async fn run_server(server_config: Arc<WsServerConfig>) -> anyhow::Result<()
|
|||
let mut tls_context = if let Some(tls_config) = &server_config.tls {
|
||||
let tls_context = TlsContext {
|
||||
tls_acceptor: Arc::new(tls::tls_acceptor(tls_config, Some(vec![b"h2".to_vec(), b"http/1.1".to_vec()]))?),
|
||||
tls_reloader: TlsReloader::new(server_config.clone())?,
|
||||
tls_reloader: TlsReloader::new_for_server(server_config.clone())?,
|
||||
tls_config,
|
||||
};
|
||||
Some(tls_context)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use crate::{tls, WsServerConfig};
|
||||
use crate::tunnel::tls_reloader::TlsReloaderState::{Client, Server};
|
||||
use crate::{tls, WsClientConfig, WsServerConfig};
|
||||
use anyhow::Context;
|
||||
use log::trace;
|
||||
use notify::{EventKind, RecommendedWatcher, Watcher};
|
||||
|
@ -10,41 +11,108 @@ use std::thread;
|
|||
use std::time::Duration;
|
||||
use tracing::{error, info, warn};
|
||||
|
||||
struct TlsReloaderState {
|
||||
struct TlsReloaderServerState {
|
||||
fs_watcher: Mutex<RecommendedWatcher>,
|
||||
tls_reload_certificate: AtomicBool,
|
||||
server_config: Arc<WsServerConfig>,
|
||||
cert_path: PathBuf,
|
||||
key_path: PathBuf,
|
||||
client_ca_path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
struct TlsReloaderClientState {
|
||||
fs_watcher: Mutex<RecommendedWatcher>,
|
||||
tls_reload_certificate: AtomicBool,
|
||||
client_config: Arc<WsClientConfig>,
|
||||
cert_path: PathBuf,
|
||||
key_path: PathBuf,
|
||||
}
|
||||
|
||||
enum TlsReloaderState {
|
||||
Empty,
|
||||
Server(Arc<TlsReloaderServerState>),
|
||||
Client(Arc<TlsReloaderClientState>),
|
||||
}
|
||||
|
||||
impl TlsReloaderState {
|
||||
fn fs_watcher(&self) -> &Mutex<RecommendedWatcher> {
|
||||
match self {
|
||||
TlsReloaderState::Empty => unreachable!(),
|
||||
Server(this) => &this.fs_watcher,
|
||||
Client(this) => &this.fs_watcher,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TlsReloader {
|
||||
state: Option<Arc<TlsReloaderState>>,
|
||||
state: TlsReloaderState,
|
||||
}
|
||||
|
||||
impl TlsReloader {
|
||||
pub fn new(server_config: Arc<WsServerConfig>) -> anyhow::Result<Self> {
|
||||
pub fn new_for_server(server_config: Arc<WsServerConfig>) -> anyhow::Result<Self> {
|
||||
// If there is no custom certificate and private key, there is nothing to watch
|
||||
let Some((Some(cert_path), Some(key_path))) = server_config
|
||||
let Some((Some(cert_path), Some(key_path), client_ca_certs)) = server_config
|
||||
.tls
|
||||
.as_ref()
|
||||
.map(|t| (&t.tls_certificate_path, &t.tls_key_path))
|
||||
.map(|t| (&t.tls_certificate_path, &t.tls_key_path, &t.tls_client_ca_certs_path))
|
||||
else {
|
||||
return Ok(Self { state: None });
|
||||
return Ok(Self {
|
||||
state: TlsReloaderState::Empty,
|
||||
});
|
||||
};
|
||||
|
||||
let this = Arc::new(TlsReloaderState {
|
||||
let this = Arc::new(TlsReloaderServerState {
|
||||
fs_watcher: Mutex::new(notify::recommended_watcher(|_| {})?),
|
||||
tls_reload_certificate: AtomicBool::new(false),
|
||||
cert_path: cert_path.to_path_buf(),
|
||||
key_path: key_path.to_path_buf(),
|
||||
client_ca_path: client_ca_certs.as_ref().map(|x| x.to_path_buf()),
|
||||
server_config,
|
||||
});
|
||||
|
||||
info!("Starting to watch tls certificate and private key for changes to reload them");
|
||||
info!("Starting to watch tls certificates and private key for changes to reload them");
|
||||
let mut watcher = notify::recommended_watcher({
|
||||
let this = this.clone();
|
||||
let this = Server(this.clone());
|
||||
|
||||
move |event: notify::Result<notify::Event>| Self::handle_fs_event(&this, event)
|
||||
move |event: notify::Result<notify::Event>| Self::handle_server_fs_event(&this, event)
|
||||
})
|
||||
.with_context(|| "Cannot create tls certificate watcher")?;
|
||||
|
||||
watcher.watch(&this.cert_path, notify::RecursiveMode::NonRecursive)?;
|
||||
watcher.watch(&this.key_path, notify::RecursiveMode::NonRecursive)?;
|
||||
if let Some(client_ca_path) = &this.client_ca_path {
|
||||
watcher.watch(client_ca_path, notify::RecursiveMode::NonRecursive)?;
|
||||
}
|
||||
*this.fs_watcher.lock() = watcher;
|
||||
|
||||
Ok(Self { state: Server(this) })
|
||||
}
|
||||
|
||||
pub fn new_for_client(client_config: Arc<WsClientConfig>) -> anyhow::Result<Self> {
|
||||
// If there is no custom certificate and private key, there is nothing to watch
|
||||
let Some((Some(cert_path), Some(key_path))) = client_config
|
||||
.remote_addr
|
||||
.tls()
|
||||
.map(|t| (&t.tls_certificate_path, &t.tls_key_path))
|
||||
else {
|
||||
return Ok(Self {
|
||||
state: TlsReloaderState::Empty,
|
||||
});
|
||||
};
|
||||
|
||||
let this = Arc::new(TlsReloaderClientState {
|
||||
fs_watcher: Mutex::new(notify::recommended_watcher(|_| {})?),
|
||||
tls_reload_certificate: AtomicBool::new(false),
|
||||
cert_path: cert_path.to_path_buf(),
|
||||
key_path: key_path.to_path_buf(),
|
||||
client_config,
|
||||
});
|
||||
|
||||
info!("Starting to watch tls certificates and private key for changes to reload them");
|
||||
let mut watcher = notify::recommended_watcher({
|
||||
let this = Client(this.clone());
|
||||
|
||||
move |event: notify::Result<notify::Event>| Self::handle_client_fs_event(&this, event)
|
||||
})
|
||||
.with_context(|| "Cannot create tls certificate watcher")?;
|
||||
|
||||
|
@ -52,24 +120,25 @@ impl TlsReloader {
|
|||
watcher.watch(&this.key_path, notify::RecursiveMode::NonRecursive)?;
|
||||
*this.fs_watcher.lock() = watcher;
|
||||
|
||||
Ok(Self { state: Some(this) })
|
||||
Ok(Self { state: Client(this) })
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn should_reload_certificate(&self) -> bool {
|
||||
match &self.state {
|
||||
None => false,
|
||||
Some(this) => this.tls_reload_certificate.swap(false, Ordering::Relaxed),
|
||||
TlsReloaderState::Empty => false,
|
||||
Server(this) => this.tls_reload_certificate.swap(false, Ordering::Relaxed),
|
||||
Client(this) => this.tls_reload_certificate.swap(false, Ordering::Relaxed),
|
||||
}
|
||||
}
|
||||
|
||||
fn try_rewatch_certificate(this: Arc<TlsReloaderState>, path: PathBuf) {
|
||||
fn try_rewatch_certificate(this: TlsReloaderState, path: PathBuf) {
|
||||
thread::spawn(move || {
|
||||
while !path.exists() {
|
||||
warn!("TLS file {:?} does not exist anymore, waiting for it to be created", path);
|
||||
thread::sleep(Duration::from_secs(10));
|
||||
}
|
||||
let mut watcher = this.fs_watcher.lock();
|
||||
let mut watcher = this.fs_watcher().lock();
|
||||
let _ = watcher.unwatch(&path);
|
||||
let Ok(_) = watcher
|
||||
.watch(&path, notify::RecursiveMode::NonRecursive)
|
||||
|
@ -88,11 +157,21 @@ impl TlsReloader {
|
|||
paths: vec![path],
|
||||
attrs: Default::default(),
|
||||
};
|
||||
Self::handle_fs_event(&this, Ok(event));
|
||||
|
||||
match &this {
|
||||
Server(_) => Self::handle_server_fs_event(&this, Ok(event)),
|
||||
Client(_) => Self::handle_client_fs_event(&this, Ok(event)),
|
||||
TlsReloaderState::Empty => {}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn handle_fs_event(this: &Arc<TlsReloaderState>, event: notify::Result<notify::Event>) {
|
||||
fn handle_server_fs_event(this: &TlsReloaderState, event: notify::Result<notify::Event>) {
|
||||
let this = match this {
|
||||
TlsReloaderState::Empty | Client(_) => return,
|
||||
Server(st) => st,
|
||||
};
|
||||
|
||||
let event = match event {
|
||||
Ok(event) => event,
|
||||
Err(err) => {
|
||||
|
@ -115,12 +194,12 @@ impl TlsReloader {
|
|||
}
|
||||
Err(err) => {
|
||||
warn!("Error while loading TLS certificate {:?}", err);
|
||||
Self::try_rewatch_certificate(this.clone(), path.to_path_buf());
|
||||
Self::try_rewatch_certificate(Server(this.clone()), path.to_path_buf());
|
||||
}
|
||||
},
|
||||
EventKind::Remove(_) => {
|
||||
warn!("TLS certificate file has been removed, trying to re-set a watch for it");
|
||||
Self::try_rewatch_certificate(this.clone(), path.to_path_buf());
|
||||
Self::try_rewatch_certificate(Server(this.clone()), path.to_path_buf());
|
||||
}
|
||||
EventKind::Access(_) | EventKind::Other | EventKind::Any => {
|
||||
trace!("Ignoring event {:?}", event);
|
||||
|
@ -137,12 +216,142 @@ impl TlsReloader {
|
|||
}
|
||||
Err(err) => {
|
||||
warn!("Error while loading TLS private key {:?}", err);
|
||||
Self::try_rewatch_certificate(this.clone(), path.to_path_buf());
|
||||
Self::try_rewatch_certificate(Server(this.clone()), path.to_path_buf());
|
||||
}
|
||||
},
|
||||
EventKind::Remove(_) => {
|
||||
warn!("TLS private key file has been removed, trying to re-set a watch for it");
|
||||
Self::try_rewatch_certificate(this.clone(), path.to_path_buf());
|
||||
Self::try_rewatch_certificate(Server(this.clone()), path.to_path_buf());
|
||||
}
|
||||
EventKind::Access(_) | EventKind::Other | EventKind::Any => {
|
||||
trace!("Ignoring event {:?}", event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(client_ca_path) = &this.client_ca_path {
|
||||
if let Some(path) = event.paths.iter().find(|p| p.ends_with(client_ca_path)) {
|
||||
match event.kind {
|
||||
EventKind::Create(_) | EventKind::Modify(_) => {
|
||||
match tls::load_certificates_from_pem(client_ca_path) {
|
||||
Ok(tls_certs) => {
|
||||
if let Some(client_certs) = &tls.tls_client_ca_certificates {
|
||||
*client_certs.lock() = tls_certs;
|
||||
this.tls_reload_certificate.store(true, Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
warn!("Error while loading TLS client certificate {:?}", err);
|
||||
Self::try_rewatch_certificate(Server(this.clone()), path.to_path_buf());
|
||||
}
|
||||
}
|
||||
}
|
||||
EventKind::Remove(_) => {
|
||||
warn!("TLS client certificate has been removed, trying to re-set a watch for it");
|
||||
Self::try_rewatch_certificate(Server(this.clone()), path.to_path_buf());
|
||||
}
|
||||
EventKind::Access(_) | EventKind::Other | EventKind::Any => {
|
||||
trace!("Ignoring event {:?}", event);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_client_fs_event(this: &TlsReloaderState, event: notify::Result<notify::Event>) {
|
||||
let this = match this {
|
||||
TlsReloaderState::Empty | Server(_) => return,
|
||||
Client(st) => st,
|
||||
};
|
||||
|
||||
let event = match event {
|
||||
Ok(event) => event,
|
||||
Err(err) => {
|
||||
error!("Error while watching tls certificate and private key for changes {:?}", err);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
if event.kind.is_access() {
|
||||
return;
|
||||
}
|
||||
|
||||
let tls = this.client_config.remote_addr.tls().unwrap();
|
||||
if let Some(path) = event.paths.iter().find(|p| p.ends_with(&this.cert_path)) {
|
||||
match event.kind {
|
||||
EventKind::Create(_) | EventKind::Modify(_) => match (
|
||||
tls::load_certificates_from_pem(&this.cert_path),
|
||||
tls::load_private_key_from_file(&this.key_path),
|
||||
) {
|
||||
(Ok(tls_certs), Ok(tls_key)) => {
|
||||
let tls_connector = tls::tls_connector(
|
||||
tls.tls_verify_certificate,
|
||||
this.client_config.remote_addr.scheme().alpn_protocols(),
|
||||
!tls.tls_sni_disabled,
|
||||
Some(tls_certs),
|
||||
Some(tls_key),
|
||||
);
|
||||
let tls_connector = match tls_connector {
|
||||
Ok(cn) => cn,
|
||||
Err(err) => {
|
||||
error!("Error while creating TLS connector {:?}", err);
|
||||
return;
|
||||
}
|
||||
};
|
||||
*tls.tls_connector.write() = tls_connector;
|
||||
this.tls_reload_certificate.store(true, Ordering::Relaxed);
|
||||
}
|
||||
(Err(err), _) | (_, Err(err)) => {
|
||||
warn!("Error while loading TLS certificate {:?}", err);
|
||||
Self::try_rewatch_certificate(Client(this.clone()), path.to_path_buf());
|
||||
}
|
||||
},
|
||||
EventKind::Remove(_) => {
|
||||
warn!("TLS certificate file has been removed, trying to re-set a watch for it");
|
||||
Self::try_rewatch_certificate(Client(this.clone()), path.to_path_buf());
|
||||
}
|
||||
EventKind::Access(_) | EventKind::Other | EventKind::Any => {
|
||||
trace!("Ignoring event {:?}", event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(path) = event
|
||||
.paths
|
||||
.iter()
|
||||
.find(|p| p.ends_with(tls.tls_key_path.as_ref().unwrap()))
|
||||
{
|
||||
match event.kind {
|
||||
EventKind::Create(_) | EventKind::Modify(_) => match (
|
||||
tls::load_certificates_from_pem(&this.cert_path),
|
||||
tls::load_private_key_from_file(&this.key_path),
|
||||
) {
|
||||
(Ok(tls_certs), Ok(tls_key)) => {
|
||||
let tls_connector = tls::tls_connector(
|
||||
tls.tls_verify_certificate,
|
||||
this.client_config.remote_addr.scheme().alpn_protocols(),
|
||||
!tls.tls_sni_disabled,
|
||||
Some(tls_certs),
|
||||
Some(tls_key),
|
||||
);
|
||||
let tls_connector = match tls_connector {
|
||||
Ok(cn) => cn,
|
||||
Err(err) => {
|
||||
error!("Error while creating TLS connector {:?}", err);
|
||||
return;
|
||||
}
|
||||
};
|
||||
*tls.tls_connector.write() = tls_connector;
|
||||
this.tls_reload_certificate.store(true, Ordering::Relaxed);
|
||||
}
|
||||
(Err(err), _) | (_, Err(err)) => {
|
||||
warn!("Error while loading TLS private key {:?}", err);
|
||||
Self::try_rewatch_certificate(Client(this.clone()), path.to_path_buf());
|
||||
}
|
||||
},
|
||||
EventKind::Remove(_) => {
|
||||
warn!("TLS private key file has been removed, trying to re-set a watch for it");
|
||||
Self::try_rewatch_certificate(Client(this.clone()), path.to_path_buf());
|
||||
}
|
||||
EventKind::Access(_) | EventKind::Other | EventKind::Any => {
|
||||
trace!("Ignoring event {:?}", event);
|
||||
|
|
Loading…
Reference in a new issue