How to correctly setup TLS/SSL on localhost using http-server? - https

I'm using http-server to serve my local project through HTTPS. To create the key.pem and the cert.pem files, I followed the documentation:
First, you need to make sure that openssl is installed correctly, and
you have key.pem and cert.pem files. You can generate them using this
command:
openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem
You will be prompted with a few questions after
entering the command. Use 127.0.0.1 as value for "Common name" if you
want to be able to install the certificate in your OS's root
certificate store or browser so that it is trusted.
This generates a cert-key pair and it will be valid for 3650 days
(about 10 years).
Then you need to run the server with -S for enabling SSL and -C for
your certificate file.
http-server -S -C cert.pem
I used the openssl.exe come with the Git, and installed the generated certificate on Windows (onto the "Trusted Root Certification Authorities" entry). Here is the output after running the server:
Starting up http-server, serving ./ through https
http-server version: 14.1.1
http-server settings:
CORS: disabled
Cache: 3600 seconds
Connection Timeout: 120 seconds
Directory Listings: visible
AutoIndex: visible
Serve GZIP Files: false
Serve Brotli Files: false
Default File Extension: none
Available on:
https://10.20.30.232:8080
https://192.168.56.1:8080
https://192.168.1.126:8080
https://127.0.0.1:8080
Hit CTRL-C to stop the server
But, when I access the https://127.0.0.1:8080, I'm encountered with the following error on Google Chrome:
Your connection is not private
...
NET::ERR_CERT_COMMON_NAME_INVALID
Subject: 127.0.0.1
Issuer: 127.0.0.1
...
This server could not prove that it is 127.0.0.1; its security certificate does not specify Subject Alternative Names.
And, the following is the error message Mozilla Firefox presents:
127.0.0.1:8080 uses an invalid security certificate.
The certificate does not come from a trusted source.
Error code: MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY
https://127.0.0.1:8080/
The server uses a certificate with a basic constraints extension identifying it
as a certificate authority. For a properly-issued certificate, this should not
be the case.
HTTP Strict Transport Security: false
HTTP Public Key Pinning: false
So, what am I missing on setting up the HTTPS server to avoid the aforementioned errors?!

Chrome should accept this certificate if you explicitly list 127.0.0.1 as a "Subject Alternative Name" (SAN) of type IP. You can do so by adding -addext "subjectAltName = IP:127.0.0.1" to the openssl command:
openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem -addext "subjectAltName = IP:127.0.0.1"
Firefox complains about a very different issue, i.e. that a certificate with a basic constraints extension with CA:TRUE is being used as an end-entity certificate. See also: https://bugzilla.mozilla.org/show_bug.cgi?id=1034124
You could try to generate the certificate without the basic constraints extenstion.
The shortcut solution would be to leverage existing solutions like https://github.com/FiloSottile/mkcert or https://github.com/davewasmer/devcert.

Related

HTTPS for SpringBoot Application on Ubuntu Server (Hosted on STRATO)

i try to develop my SpringBoot Backend Application on STRATO.de
i buyed a ubunutu vServer and runned my spring app via jar.
but backend (http) and frontend (https) cant connect because of the ssl. I created a self signed jks file for my spring boot app and the https works but when i open my backend ip adress and port firstly i get the message "this ist not a secure connection" and i have to accept the certificate. After that everything works fine.
Is there a Option to get a secure connection? i try to use LetsEncrypt CerBot etc. nothing works. The Tutorials are not for the newest Ubuntu version.
Where can i secure my SpringBoot app via HTTPS without a SelfSigned certificate?
Both frontend & backend needs to have https connection for secured communication. Hence it's necessary to use https for your spring-boot application. Self signed jks is only good for development, which is not meant to be used for production.
You may follow these steps:
Install OpenSSL if not available in your server. How to install OpenSSL
Run this command, # openssl req -new -newkey rsa:2048 -nodes -keyout yourkey.key -out yourcsr.csr
Here, yourkey.key = It’s your private key and
yourcsr.csr = Your Certificate Signing Request which needs to send to CA authorities. While creating CSR, it will ask some questions, which will be later required for keystore. Hence, save them properly.
Buy your SSL certificate from your preferable registrant, ie name.com
Send your yourcsr.csr file information to the registrants. Please follow their respective instructions.
Once approved, you will receive two files. yourserver.crt and yourca.crt
# openssl pkcs12 -export -in yourserver.crt -inkey yourkey.key -out yourkeystore.p12 -name somealias -certfile yourca.crt -caname root
It will ask some questions, pls make sure it matches the information that you provided earlier while creating the CSR. It will prompt for password for the keystore. This command will create a keystore named yourkeystore.p12
# keytool -importkeystore -srckeystore yourkeystore.p12 -srcstoretype PKCS12 -destkeystore yourkeystore.jks -deststoretype JKS -deststorepass newkeystorepassword -destkeypass newkeypassword Convert to JKS, if you specifically want to use JKS for spring boot. This command will create a keystore named yourkeystore.jks
Put required information at application.properties.
server.port: 8443
server.ssl.key-store: classpath: yourkeystore.jks
server.ssl.key-store-password: newkeystorepassword
server.ssl.key-store-type: jks
server.ssl.key-alias: somealias
server.ssl.key-password: newkeypassword

LetsEncrypt cert as p12 fails instanceof CertEntry test in Spring Boot

I used LetsEncrypt's certbot to generate the cert and key pems:
sudo certbot certonly -a standalone -d footeware.ca
...and converted them to a p12:
openssl pkcs12 -export -in fullchain.pem -inkey privkey.pem -out keystore.p12 -name tomcat -CAfile chain.pem -caname root
I moved the p12 to my development machine into my eclipse project's resources folder.
When I start the application and debug thru sun.security.pkcs12.PKCS12KeyStore#engineIsCertificateEntry, it finds the aliased entry but states it's not an instanceof sun.security.pkcs12.PKCS12KeyStore.CertEntry but rather a sun.security.pkcs12.PKCS12KeyStore$PrivateKeyEntry and so it fails with:
java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
keytool -list on the p12:
Alias name: tomcat
Creation date: Jan. 3, 2022
Entry type: PrivateKeyEntry
Certificate chain length: 3
Certificate[1]:
Owner: CN=footeware.ca
Issuer: CN=R3, O=Let's Encrypt, C=US
What have I done wrong? Should the PrivateKeyEntry be something else?
Thanks #Saif for that link.
I did:
sudo update-ca-certificates -f
sudo /var/lib/dpkg/info/ca-certificates-java.postinst configure
...and used my original keystore.p12 (seems there was nothing wrong with it).
The solution was to change my application.properties' values to:
server.ssl.trust-store=file:/etc/ssl/certs/java/cacerts
server.ssl.trust-store-password=changeit
server.ssl.trust-store-type=JKS
I had been setting those properties to the keystore.p12 thinking they were one and the same (noob).
I deployed and started the appication jar, set my router to forward 443 to my server#8443 (instead of 80 to 8090 as it was) and I'm in with a happy https indicator!
Now I just have to fix the broken css that upgrading bootstrap seems to have caused. Pain that the cert prevents me from using localhost now as it only supports footeware.ca.
Any ideas there?

How to set up an https server with a self-signed certificate in golang

I'm trying to set up an https server (http.ListenAndServeTLS()) with a self-signed certificate to listen for a webhook updates from a service (I'm sure this service has no problem working with such certificates), but it fails and constantly prints
<date> <time> http: TLS handshake error from <IP>: remote error: tls: bad certificate
I've looked for solutions and tried several (setting InsecureSkipVerify to true in TLSConfig, adding my certificate to the Certificates field of the config or signing another certificate with self-signed one and appending the latter to the RootCAs), but nothing solves the issue (the last solution unsurprisingly changes the error to unknown certificate authority).
As I've mentioned, I'm pretty sure the problem isn't related to the service I'm trying to listen to, so there must be something really simple that I'm missing about setting up a server in Go. My code looks something like this:
rootCAs, _ := x509.SystemCertPool()
if rootCAs == nil {
rootCAs = x509.NewCertPool()
}
certs, _ := ioutil.ReadFile(CA_PATH)
_ = rootCAs.AppendCertsFromPEM(certs);
server := http.Server{
Addr: "",
Handler: nil,
TLSConfig: &tls.Config{
InsecureSkipVerify: true,
Certificates: []tls.Certificate{ my_cert },
RootCAs: rootCAs,
},
}
fmt.Println(server.ListenAnsServeTLS(PEM_PATH, KEY_PATH))
As mentioned in RFC2246, the handshake protocol establishes a TLS session and negotiates the security permissions between the client and the server. By default, your machine already trusts a set of certificates from many Certificate Authorities like: GoDaddy, IdenTrust, DigiCert, etc. When you are the Certificate Authority (self-signed certificate way), you need to provide the certificate to the client, and the client needs to trust that certificate. So what you need to do is:
after openssl tool installation, run the command below:
openssl req -new -subj "/C=US/ST=Utah/CN=localhost" -newkey rsa:2048 -nodes -keyout localhost.key -out localhost.csr
that command generates a localhost.key file which is the private key and localhost.csr which is the certificate signing request (CSR) that contains the public key. The CN passed in -subj is the most important field because some browsers like chrome require that information. CN means Common Name and it is the domain name that you would like to have SSL secured. Then, you need to generate the certificate file:
openssl x509 -req -days 365 -in localhost.csr -signkey localhost.key -out localhost.crt
The localhost.crt file is generated by the command above and it's the self-signed certificate signed by your own localhost.key private key. The x509 flag states the standard format of an SSL/TLS certificate which is X.509.
After that you need to use the cert and key to serve the https self signed server:
log.Fatal(http.ListenAndServeTLS("8081", "localhost.crt","localhost.key", router))
In the client side, is very important that it trusts the server certificate, instead of using curl's -k parameter, that parameter will ignore TLS protocol. If you're using a linux OS, install the ca-certificates package and then copy the localhost.crt to ca-certificates folder:
cp localhost.crt /usr/local/share/ca-certificates/localhost.crt
finally trust that certificate with the command below:
update-ca-certificates
If you're using a different OS than linux you can follow one of these steps: Mac Os, Windows, Linux. You'll find a complete example in this github repo.
Create a directory golangssl and enter it
mkdir golangssl
cd golangssl
Generate a selfsigned key and cert (install openssl if not yet installed)
openssl genrsa -out server.key 2048
openssl ecparam -genkey -name secp384r1 -out server.key
openssl req -new -x509 -sha256 -key server.key -out server.crt -days 3650
Create a file server.go with the following content
package main
import (
"log"
"net/http"
)
func SecureServer(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Content-Type", "text/plain")
w.Write([]byte("Secure Hello World.\n"))
}
func main() {
http.HandleFunc("/secure", SecureServer)
err := http.ListenAndServeTLS(":443", "server.crt", "server.key", nil)
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
Run the server (needs root rights, because of binding of port 443)
sudo go run server.go
Execute a request (-k for ignoring the self signed certificate)
curl -k https://localhost/secure
Output should be
Secure Hello World.

How to implement Burp suite's custom SSL Certificate?

In Burp Suite, from Project Options -> SSL we can import PKCS#12 files with password for specific hostnames.
I tried manually using commands below to export block and key files and then pass them to my http client in golang using tls.LoadX509KeyPair(). But upon sending any requests, I receive remote error: tls: handshake failure.
These are the commands I used:
openssl pkcs12 -in cert.p12 -clcerts -nokeys -out usercert.pem
openssl pkcs12 -in cert.p12 -nocerts -out userkey.pem -nodes
What am I missing?
If using a self-signed certificate specify InsecureSkipVerify: true in your tls configuration. Pulled from the documentation:
// InsecureSkipVerify controls whether a client verifies the
// server's certificate chain and host name.
// If InsecureSkipVerify is true, TLS accepts any certificate
// presented by the server and any host name in that certificate.
// In this mode, TLS is susceptible to man-in-the-middle attacks.
// This should be used only for testing.```
Otherwise, add your certificate to the Certificates list in your tls configuration.

Has anyone ever successfully connected a MAC to an Azure P2S network gateway? None of the documentation works for me

Starting with an empty directory:
Generate CAroot private key
$ openssl genrsa -aes256 -out dcsAzureVPN.key 2048
Generate a CARoot certificate
$ openssl req -x509 -sha256 -new -key dcsAzureVPN.key -out dcsAzureVPN.cer -days 1825 -subj /CN="dcsAzureVPN"`
Successfully copied dcsAzureVPN.cer to VPN gateway and saved (see attached screenshot)
Generate Certificate Request (CSR)
$ openssl genrsa -out dcsAzureClientCert.key 2048
$ openssl req -new -out tjaClientCert.req -key dcsAzureClientCert.key -subj /CN="dcsAzureVPN"`
Generate signed Client Certificate from CSR
$ openssl x509 -req -sha256 -in tjaClientCert.req -out dcsAzureClientCert.cer -CAkey dcsAzureVPN.key -CA dcsAzureVPN.cer -days 1825 -CAcreateserial -CAserial serial
Signature ok
subject=/CN=dcsAzureVPN
Pack key and certificate in .pfx format
$ openssl pkcs12 -export -out dcsAzureVPNClient.pfx -inkey dcsAzureClientCert.key -in dcsAzureClientCert.cer -certfile dcsAzureVPN.cer
Copy client cert to my Keychain
Make dcsAzure VPN a trusted cert.
Select dcsAzureVPN as the client certificate for my VPN connection
Try to connect. Connection fails with an error: User Authentication failed
What am I doing wrong?
I finally found the problem. It turns out the Local ID has to match the client certificate subject, not the name of your client certificate file.
You have to manually configure the native IKEv2 VPN client on every Mac that will connect to Azure. You could use these steps to configure the native VPN client on Mac for certificate authentication.
Moreover, you could refer to this to troubleshoot Point-to-Site VPN connections from Mac OS X VPN clients.
Additionally, no matter what client OS you want to connect from, you must always have a client certificate. You can generate a client certificate from either a root certificate that was generated using an Enterprise CA solution or a self-signed root certificate. See the PowerShell, MakeCert, or Linux instructions for steps to generate a client certificate.
Please let me know if this works.
Whoever stumbles up on this solution: It is working if you change the Client certificate's subj from dcsAzureVPN to (for example) dcsAzureVPNSubj and use it in the connection tab for Local ID.
So instead of this:
openssl req -new -out tjaClientCert.req -key dcsAzureClientCert.key -subj /CN="dcsAzureVPN"
Use this:
openssl req -new -out tjaClientCert.req -key dcsAzureClientCert.key -subj /CN="dcsAzureVPNSubj"
and use the dcsAzureVPNSubj for Local id on the MacOS VPN connection tab.
Worked on the following machine:
20.5.0 Darwin Kernel Version 20.5.0: root:«gibberish»/RELEASE_ARM64_T8101 arm64
Big Sur version: 11.4

Resources