Nginx 1.9.5 (linux Centos7)--> MS IIS 8.5
So i try to use nginx as client revers proxy for IIS where need client certificate authentication at IIS level.
nginx:443->>IIS:443+client certificate authentications.
example location proxy pass
also here are commented commands which i try.
location ^~ /test/ {
#proxy_buffering off;
#proxy_http_version 1.0;
#proxy_request_buffering off;
#proxy_set_header Connection "Keep-Alive";
#proxy_set_header X-SSL-CERT $ssl_client_cert;
# proxy_ssl_name domain.lv;
#proxy_ssl_trusted_certificate /etc/nginx/ssl/root/CA.pem;
#proxy_ssl_verify_depth 2;
proxy_set_header HOST domain.com;
proxy_ssl_certificate /etc/nginx/ssl/test.pem;
proxy_ssl_certificate_key /etc/nginx/ssl/test_key.pem;
proxy_ssl_verify off;
proxy_pass https://10.2.4.101/;
}
At IIS simple.
create new website.
import CA cert in trusted root.
set ssl cert required.
Test what i get :
Directly browser to IIS client cert required--worked.
Nginx to other nginx client cert required--worked.
Nginx to IIS client cert ignore--worked
Nginx to IIS client cert required or accept - NOT work
ERROR:
Nginx side:
*4622 upstream timed out (110: Connection timed out) while reading response header from upstream
IIS side:
500 0 64 119971
So i hope someone could know why?
EDIT
1. also try from different server with nginx 1.8 nothing helped..
proxy_ssl_verify off;
proxy_ssl_certificate /etc/nginx/ssl/test/test.pem;
proxy_ssl_certificate_key /etc/nginx/ssl/test/test_key.pem;
proxy_pass https://domain.com;
2.Try same with apache 2.4 all worked with
SSLProxyEngine On
SSLProxyVerify none
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off
SSLProxyCheckPeerExpire off
SSLProxyMachineCertificateFile /etc/httpd/ssl/test.pem
ProxyPass "/test" "https://domain.com"
Maybe something with ssl renegotiation in nginx???
Your hunch about TLS renegotiation is correct. Nginx has not allowed TLS renegotiation since version 0.8.23 (see http://nginx.org/en/CHANGES). However, by default IIS will use TLS renegotiation when requesting a client certificate. (I haven't been able to find the reasons for this - I would be grateful if someone could enlighten me!)
You can use a packet sniffer such as wireshark to see this in action:
IIS and Nginx first perform a TLS handshake using the server certificate only.
Nginx requests the resource.
The resource requires client authentication, so IIS sends a 'Hello Request' message to Nginx to initiate TLS renegotiation.
Nginx doesn't respond to the Hello Request as TLS renegotiation has been disabled.
IIS then closes the connection as it gets no response. (See the section on renegotiation at https://technet.microsoft.com/en-us/library/cc783349(v=ws.10).aspx)
To solve this problem, you must force IIS to request a client certificate on the initial TLS handshake. You can do this using the netsh utility from powershell or the command line:
Open a powershell prompt with administrator rights.
Enter netsh
Enter http
Enter show sslcert. You should see a list of all current SSL bindings on your machine:
Make a note of the IP:port and certificate hash of the certificate that you want to enable client certificate negotiations for. We are now going to delete this binding and re-add it with the Negotiate Client Certificate property set to enabled. In this example, the IP:port is 0.0.0.0:44300 and the certificate hash is 71472159d7233d56bc90cea6d0c26f7a29db1112.
Enter delete sslcert ipport=[IP:port from above]
Enter add sslcert ipport=[IP:port from above] certhash=[certificate hash from above] appid={[any random GUID (can be the same one from the show sslcert output)]} certstorename=MY verifyclientcertrevocation=enable verifyrevocationwithcachedclientcertonly=disable clientcertnegotiation=enable
You can now confirm that this has worked by running show sslcert again. You should see an almost identical output, but with Negotiate Client Certificate set to Enabled:
Note that this method only works for individual certificates - if you need to change or renew the certificate you will have to run these steps again. Of course, you should wrap these up in a batch script or MSI installer custom action for ease of deployment and maintenance.
Related
I have configured my nginx to use the certificate and private_key that I downloaded from cloudflare crypto.
This is my nginx.conf file-
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name autocaptions.app *.autocaptions.app;
location / {
proxy_pass http://127.0.0.1:7887;
}
ssl on;
ssl_certificate /home/ubuntu/sslcerts/autocaptions.pem;
ssl_certificate_key /home/ubuntu/sslcerts/private-key.pem;
# ssl_client_certificate /home/ubuntu/sslcerts/cloudflare.crt;
# ssl_verify_client on;
}
# Redirect http to https
server {
listen 80;
listen [::]:80;
return 301 https://$host$request_uri;
}
I am not sure what the issue is. I have added the certificate and the private_key.
I see the following error in the browser when I try to access https://autocaptions.app -
Error in text-
autocaptions.app has a security policy called HTTP Strict Transport Security (HSTS), which means that Firefox can only connect to it securely. You can’t add an exception to visit this site.
In Cloudflare configuration, I have disabled HSTS, not sure why this error is showing up.
I have followed digitalocean tutorial to configure SSL.
You are using a certificate signed by the "Cloudflare Origin CA". Certificates issued by this CA are intended to be installed on your origin server so that the communication between the Cloudflare CDN and your origin server can be protected by a certificate.
These kind of certificates are not intended on systems facing end users (i.e. browsers). They are only intended to secure the communication between your origin server and Cloudflare. Typical end users will not have the "Cloudflare Origin CA" as a trusted CA in their browser and thus they will get a TLS error when connecting to your origin server - and this is thus what you get. But typical end users should not connect to the origin server in the first place - they should connect to the Cloudflare instance instead. Only Cloudflare itself should connect to the origin server and they will acknowledge their own CA as trusted.
Check your site's SSL Setting under Crypto tab. Change it to 'Full' or 'Flexible' if its on 'Full (Strict)'.
TL;DR #SteffenUllrich is absolutely correct and should be the accepted answer.
This is your current setup.
You are gray-clouding the DNS record, essentially exposing your origin server's IP address to the whole world.
The first problem here is that, it is similar to posting your home's address on Twitter/Facebook, saying the front door is unlocked so feel free to come in and take what you want!
Cloudflare Origin CA Certificate
|
client <---------------------HTTPS-----------------> your origin (AWS)
The second problem here is that CloudFlare Origin CA Certificate is not meant to be used for client-server connection. It's purpose is to encrypt connection between Cloudflare edge and your origin only. You can think of it as a self-signed certificate. This is the reason for the error you're seeing.
One very simple solution is to replace this origin certificate with other free or paid SSL certificate such as Let's Encrypt/Certbot. If you decide to go this way, you can then skip the rest of below explanation if you want.
If you wish to keep using Cloudflare Origin CA Certificate however, keep on reading.
The next step is to proxy your connection to Cloudflare by orange-clouding the DNS record. Connection between client and Cloudflare edge will be encrypted using Cloudflare's free (shared) Universal SSL Certificate. It will partially solve the problem, but only half of the client-server connection is encrypted, because you are using Flexible mode. Connection between Cloudflare edge and your origin will not be encrypted.
Universal SSL Certificate
|
client <---HTTPS---> Cloudflare edge <----HTTP----> your origin (AWS)
The final step if to change the SSL mode from Flexible to Full or Full (Strict). Now you will get end-to-end encryption.
Universal SSL Certificate Cloudflare Origin CA Certificate
| |
client <---HTTPS---> Cloudflare edge <----HTTPS----> your origin (AWS)
Any questions?
I am trying to proxy a old server running with self signed certificate.
Simple nginx conf:
server {
listen 8009;
location / {
proxy_ssl_verify off;
proxy_ssl_session_reuse off;
proxy_pass https://192.168.10.20:8009/;
}
}
I get SSL Handshake error in nginx log.
2018/05/02 11:31:39 [crit] 3500#2284: *1 SSL_do_handshake() failed (SSL: error:14082174:SSL routines:ssl3_check_cert_and_algorithm:dh key too small) while SSL handshaking to upstream, client: 127.0.0.1, server: , request: "GET /ping HTTP/1.1", upstream: "https://192.168.10.20:8009/ping", host: "localhost:8009"
I was hoping that adding the "proxy_ssl_verify off;" will ignore all the SSL errors but does not seem to .
ssl3_check_cert_and_algorithm:dh key too small
The problem is that the old server is providing a DH key which is considered insecure (logjam attack). This has nothing to do with certificate validation and thus trying to disable certificate validation will not help - and is a bad idea anyway.
Instead this problem need to be fixed at the server side to provide stronger DH parameters. Alternatively one might try to enforce nginx to not use DH ciphers in the first place by using the proxy_ssl_ciphers parameter. Which ciphers can be chosen there depends on what the old server supports but you might try something like HIGH:!DH as argument which allows nginx to offer all strong ciphers except the DH ciphers.
I have added a certificate in Bluemix, following this post : https://www.ibm.com/blogs/bluemix/2014/09/ssl-certificates-bluemix-custom-domains/
I can see the certificate in the domain tab, and it's the one I have uploaded.
Now I have a container running nginx, because we use it as a reverse proxy. Previously it was handling the SSL configuration, but now that it's done in Bluemix directly, we just want to accept https request, without configuring certificate.
What we did was forwarding the http requests to https, like advised in the post (explaining how to do it for node.js though). We get something like this:
server {
listen 80;
server_name *hostname.domain*;
return 301 https://$http_host$request_uri;
}
And in the 443 part, we only listen, without the ssl part:
server {
listen 443;
server_name *host.domain*;
*other stuff for reverse proxy*
}
However, when trying to access it, I get a generic error in chrome: ERR_SSL_PROTOCOL_ERROR
Firefox gives a bit more information:
An error occurred during a connection to *host.domain*. SSL received a record that exceeded the maximum permissible length. Error code: SSL_ERROR_RX_RECORD_TOO_LONG
And when I try to check the certificate from command line, I don't get any.
openssl s_client -connect *host.domain*:443
CONNECTED(00000003)
140250419918480:error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol:s23_clnt.c:782:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 7 bytes and written 289 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1.2
Cipher : 0000
Session-ID:
Session-ID-ctx:
Master-Key:
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
Start Time: 1484673167
Timeout : 300 (sec)
Verify return code: 0 (ok)
---
There's no error in nginx logs, and I can't manage to tell if the issue in on Bluemix side, or in the configuration of nginx, or if nginx allows this kind of configuration where it has to handle https requests, without the certificate configuration...
Does someone have any idea?
Many thanks.
Regards.
If you want NGINX to pass-thru SSL, you have to use the stream module.
Thanks for your answers. I was not able to check your solutions, but I talked with a technical expert from IBM meanwhile, and here is what I learned.
About the SSL pass-thru, we would need to configure each component (behind the nginx) to handle the SSL, so it seems to be harder to manage. I'm not an expert though, so I'm just reporting what I had as an answer on that point.
First, what we want should be doable by removing the public IP adress of our nginx container.
Then, by creating a route from BM load balancer to our nginx container, we should solve the issue. Then the route would be configured to forward the port 443 to the nginx on port 80 (since the container is not publicly available, there no need to handle 80 AND 443).
However, Bluemix allows route only for container groups (for now?). Unfortunately, we use docker-compose that does not allow (for now?) to create container groups on BlueMix.
So the best solution was to put back the ssl configuration in nginx. The certificate being both on BlueMix domain and nginx container. And it's working fine, so we'll just improve the procedure to update the certificate, and wait until there's a need, or a new way to do it...
K.
I generated a client-side SSL Certificate on API Gateway and added it to my nginx configuration as below:
listen *:443;
ssl on;
server_name api.xxxx.com;
ssl_certificate /etc/letsencrypt/live/api.xxxx.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.xxxx.com/privkey.pem;
ssl_verify_client on;
ssl_client_certificate /etc/nginx/ssl/awsapigateway.crt;
location /home/ubuntu/api {
# if ($ssl_client_verify != SUCCESS) { return 403; }
# proxy_pass http://my.http.public.endpoint.com;
# proxy_set_header X-Client-Verify $ssl_client_verify;
}
The client certificate doesn't work after testing via the AWS API gateway test console. It ends up with Error 400 - No required SSL certificate was sent. API Gateway should be sending its client cert to my server with each request, so that I can validate that requests are genuinely coming from API Gateway.
I believe the reason it is not working is I am adding the PEM-encoded public key from the AWS API gateway console directly to awsapigateway.crt. Is that correct?
Additionally, does nginx support self-signed client SSL certificates, which is what AWS is providing us?
Api Gateway team here.
It looks like the nginx configuration is correct. And for our simple test case we use a node server and simply write the PEM certificate from the console directly to the crt file that is set as the ca, or in this case the ssl_client_certificate.
I'd also test using the actual deployed API if for some reason the test function in the console has an issue. Make sure to use the Stage settings to specify the cert.
I use squid 3.5 with its sslbump feature for https traffic filtering. I generated my private key and cert files with openssl. However,the browser received the warning message when i open https websites that the certificate was issued by an unknown authority. I created ssl certificates with comodo but i still got the same warning message.
Is there a way to remove this warning?
# Squid normally listens to port 3128
http_port 3128 ssl-bump cert=/var/tmp/example.com.cert key=/var/tmp/example.com.private
# Squid listen Port
cert=/var/tmp/example.com.cert
# SSL Bump Config
always_direct allow all
ssl_bump server-first all
url_rewrite_program /usr/bin/sh /var/tmp/middle_squid_wrapper.sh start -C /var/tmp/middle_squid_config.rb
# required to fix HTTPS sites (if SslBump is enabled)
acl fix_ssl_rewrite method GET
acl fix_ssl_rewrite method POST
url_rewrite_access allow fix_ssl_rewrite
url_rewrite_access deny all
You don't say what client OS you are using, but it sounds very much like you didn't import your squid certificate to the correct certificate store on the client.
When you install the certificate on a Windows client it should be imported into the Trusted Root Certificate Authorities'->'certificates folder.
The client should then trust the certificate.