I am trying to use nginx as a reverse proxy to web logic with two way SSL/mutual SSL.
Client <= Two way SSL => NGINX <= Two Way SSL => WebLogic server
Client to NGINX two way SSL works fine but getting below errors on upstream connecting to web logic.
nginx debug log:
2014/08/16 22:40:53 [debug] 33741#0: *9 SSL handshake handler: 0
2014/08/16 22:40:53 [debug] 33741#0: *9 SSL_do_handshake: -1
2014/08/16 22:40:53 [debug] 33741#0: *9 SSL_get_error: 2
2014/08/16 22:40:53 [debug] 33741#0: timer delta: 5
2014/08/16 22:40:53 [debug] 33741#0: posted events 0000000000000000
2014/08/16 22:40:53 [debug] 33741#0: worker cycle
2014/08/16 22:40:53 [debug] 33741#0: kevent timer: 59840, changes: 0
2014/08/16 22:40:53 [debug] 33741#0: kevent events: 2
2014/08/16 22:40:53 [debug] 33741#0: kevent: 7: ft:-2 fl:0025 ff:00000000 d:131520 ud:00007FF263805150
2014/08/16 22:40:53 [debug] 33741#0: *9 kevent: 7: ft:-2 fl:0025 ff:00000000 d:131520 ud:00007FF263805150
2014/08/16 22:40:53 [debug] 33741#0: *9 SSL handshake handler: 1
2014/08/16 22:40:53 [debug] 33741#0: *9 SSL_do_handshake: 0
2014/08/16 22:40:53 [debug] 33741#0: *9 SSL_get_error: 1
SSL_do_handshake() failed (SSL: error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure:SSL alert number 40) while SSL handshaking to upstream
client: localhost, server: localhost, request: "GET /customers/~/xxxx/~/xxx/health HTTP/1.1", upstream: "https://xx.xx.xx.xxx:11211/customer-upstream/~/xxx/~/xxx/health/", host: "localhost:12121"
Here is my nginx configuration for upstream:
proxy_cache_path /opt/openresty/nginx/cache levels=1:2 keys_zone=data-cache:8m max_size=1000m inactive=600m;
proxy_temp_path /opt/openresty/nginx/cache/tmp;
upstream rs_backend {
server xx.xx.xx.xxx:11211;
}
server {
server_name localhost;
listen 12121 ssl;
ssl on;
ssl_verify_client on;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
#ssl_protocols TLSv1;
#ssl_ciphers SSL_RSA_WITH_RC4_128_MD5:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-RC4-SHA:ECDHE-RSA-AES128-SHA:AES128-GCM-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH:!CAMELLIA;
#ssl_ciphers HIGH:!MD5:!aNULL:!EDH:!CAMELLIA;
ssl_prefer_server_ciphers on;
proxy_ssl_session_reuse off;
large_client_header_buffers 4 32K;
ssl_certificate /etc/ssl/api-cert.pem;
ssl_certificate_key /etc/ssl/api-cert.key;
ssl_client_certificate /etc/ssl/api-cert.pem;
location /customers/
{
rewrite ^/customers/(.*) /customer-upstream/$1/ break;
proxy_redirect off;
proxy_ssl_verify on;
proxy_ssl_verify_depth 4;
proxy_ssl_trusted_certificate /etc/ssl/api-cert-nopass.pem;
proxy_pass_header Server;
proxy_http_version 1.1;
proxy_set_header Connection Keep-Alive;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host localhost:11211;
proxy_set_header Accept 'application/json;v=3';
proxy_pass https://xx.xx.xx.xxx:11211/;
#proxy_pass https://rs_backend;
}
I tried various options including commenting out below configs.
proxy_ssl_verify on;
proxy_ssl_verify_depth 4;
If I try using openssl c_client command line, I am able to connect and get 2xx response for HTTP GET request.
openssl c_client -connect xx.xx.xx.xxx:11211 -cert api-qaid-nopass.pem
Any help would be appreciated.
I have added support for two way/mutual authentication using certificate and key.
See the pull request:
https://github.com/nginx/nginx/pull/7
http://mailman.nginx.org/pipermail/nginx-devel/2014-August/005817.html
It is been validated against WebLogic 11g server which is configured for two way SSL.
proxy_ssl_trusted_certificate is used to verify the certificate of the upstream server, not to specify the client certificate which should be used when connecting to the upstream server. As far as I know there is currently now way to make ngnix use a client certificate in the upstream connection.
Related
I have a lxc setup here. In one container is the nginx running with a simple html website. In the second container is the nginx reserve proxy running. When I try to open the url https://malte-kiefer.de in the browser, I get this error:
SSL_ERROR_RX_RECORD_TOO_LONG
I check my nginx config on the reverse proxy and there is the ssl in the config:
server {
listen 80;
listen [::]:80;
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name malte-kiefer.de;
ssl_certificate /etc/nginx/ssl/malte-kiefer.de/fullchain.cer;
ssl_certificate_key /etc/nginx/ssl/malte-kiefer.de/privkey.key;
location / {
proxy_pass http://10.242.93.122:80;
proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_connect_timeout 3600;
proxy_send_timeout 3600;
proxy_read_timeout 3600;
send_timeout 3600;
}
}
When I do a curl on the proxy to the nginx container with my html site I get this, a correct answe HTTP 200:
root#proxy:~# curl -I http://10.242.93.122:80
HTTP/1.1 200 OK
Server: nginx/1.14.2
Date: Tue, 14 Jan 2020 04:44:33 GMT
Content-Type: text/html
Content-Length: 2153
Last-Modified: Sat, 07 Dec 2019 04:41:15 GMT
Connection: keep-alive
ETag: "5deb2d6b-869"
Accept-Ranges: bytes
But on my local host I get this:
% curl -I https://malte-kiefer.de ~
curl: (35) error:1408F10B:SSL routines:ssl3_get_record:wrong version number
[35] % curl -I https://malte-kiefer.de -v ~
* Trying 5.252.225.74:443...
* TCP_NODELAY set
* Trying 2a03:4000:40:e0:c47f:24ff:fe7e:b8ad:443...
* TCP_NODELAY set
* Immediate connect fail for 2a03:4000:40:e0:c47f:24ff:fe7e:b8ad: Das Netzwerk ist nicht erreichbar
* Connected to malte-kiefer.de (5.252.225.74) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
CApath: none
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* error:1408F10B:SSL routines:ssl3_get_record:wrong version number
* Closing connection 0
curl: (35) error:1408F10B:SSL routines:ssl3_get_record:wrong version number
In my nginx error log I found this:
2020/01/14 05:12:14 [info] 161#161: *1 client sent invalid request
while reading client request line, client: 127.0.0.1, server:
malte-kiefer.de, request: "PROXY TCP4 89.204.135.150 5.252.225.74
10569 443"
I want to secure a collection of web APIs I'm writing. The access to those APIs must be granted to subscribers until the subscription expires; the APIs are consumed by remote web services. So I thought that Mutual SSL is the best
way to do that.
I'm trying to set up my own CA to issue x509 certificates to clients.
This is the first time I'm doing this; so, naturally, nothing works.
This is what I want to get as end-result: I deploy my APIs using Nginx as a reverse-proxy; if the client sends a valid certificate to Nginx, the reverse proxy accepts the connection and it forwards the requests; the connection is closed otherwise. Whenever a new client signs a subscription, I generate a new certificate and send it to him/her.
So I followed this guide, that seemed to me to be more complete than others I read, and I put a self-signed ca.crt in /etc/ssl/ca/cert for signing the CSRs received from clients and I set up nginx as
server {
listen *:443 ssl;
server_name api.example.com;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_certificate /etc/ssl/certs/server.pem; #certificate from an actual CA
ssl_certificate_key /etc/ssl/private/server.key; #PK of server.pem
ssl_client_certificate /etc/ssl/ca/certs/ca.crt;
ssl_crl /etc/ssl/ca/crl/ca.crl;
ssl_verify_client on;
ssl_protocols TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on; #ensure your cert is capable
ssl_stapling_verify on; #ensure your cert is capable
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
#Redirects all traffic
location / {
proxy_pass http://mysecuredserver/api$request_uri;
limit_req zone=one burst=10;
}
}
But when I consume a Test api (it always responds with a 200 OK) using
curl -k -v --key key.pem --cert cert.pem https://api.example.com/Test
I always get the following error:
< HTTP/1.1 400 Bad Request
* Server nginx is not blacklisted
< Server: nginx
< Date: Fri, 29 Sep 2017 18:00:16 GMT
< Content-Type: text/html
< Content-Length: 224
< Connection: close
<
<html>
<head><title>400 The SSL certificate error</title></head>
<body bgcolor="white">
<center><h1>400 Bad Request</h1></center>
<center>The SSL certificate error</center>
<hr><center>nginx</center>
</body>
</html>
* Closing connection 0
* SSLv3, TLS alert, Client hello (1):
Could anybody explain to me what's wrong?
Second question: in ssl_certificate I put the cert I bought from a valid CA: is that right or should I put a cert generated using the ca.crt instead?
As discussed when you don't get much logs in Nginx you should add
debug_connection <IP>;
It will generate more logs. Which showed
2017/09/29 20:27:55 [info] 28783#0: *72 client SSL certificate verify error: (3:unable to get certificate CRL) while reading client request headers
This error occurs when you don't provide CRL for every certificate in the ssl_client_certificate chain.
Below are similar thread showing the same issue
https://serverfault.com/questions/501912/nginx-proxy-ssl-clr-400-bad-request-error
Nginx unable to get certificate CRL
You need to specify the directive ssl_crl and give it the CRL file
ssl_crl /etc/ssl/certs/crl/ca.crl;
Additionally, you should verify that ssl_certificate refers to the certificate created by your CA for your server:
ssl_certificate /etc/ssl/ca/certs/server.pem; #signed by your CA
ssl_certificate_key /etc/ssl/ca/private/server.key; #PK used to generate
#server.pem
ssl_client_certificate /etc/ssl/ca/certs/ca.crt;
ssl_crl /etc/ssl/ca/crl/ca.crl; #CRL of the
#ssl_client_certificate and
#its chain
I am trying to connect my remote nginx server which is configured to use ssl.
I fired a command
$curl https://10.73.80.197:8080/
but after that i am getting error. Here is the whole log-
* Hostname was NOT found in DNS cache
* Trying 10.73.80.197...
* Connected to 10.73.80.197 (10.73.80.197) port 80 (#0)
* successfully set certificate verify locations:
* CAfile: none
CApath: /etc/ssl/certs
* SSLv3, TLS handshake, Client hello (1):
* error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol
* Closing connection 0
curl: (35) error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol
as explained in several other articles:
curl: (35) error:1408F10B:SSL routines:ssl3_get_record:wrong version number
Curl returns "Unknown protocol"
this kind of curl error is often the result of using a web proxy over https instead of http
you should check your https_proxy env variable
if you have something like
https://myproxy.example.com:8080/
then you should change and set the following
https_proxy=http://myproxy.example.com:8080/
I encountered this today and in my case it was a misconfiguration in my nginx.conf file. My configuration contained something like this:
server {
listen 443;
listen [::]:443;
# Single underscore means 'matches any server name'
server_name _;
root /usr/share/nginx/html;
# Only allow more recent (still secure) versions of TLS
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
# Explicitly set list of supported ciphers
ssl_ciphers ECDH+AESGCM:ECDH+AES256-CBC:ECDH+AES128-CBC:DH+3DES:!ADH:!AECDH:!MD5;
ssl_certificate "/etc/pki/atmloader/server.crt";
ssl_certificate_key "/etc/pki/atmloader/server.pem";
# ...
}
but it should have looked like this:
server {
listen 443 ssl;
listen [::]:443 ssl;
# Single underscore means 'matches any server name'
server_name _;
root /usr/share/nginx/html;
# Only allow more recent (still secure) versions of TLS
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
# Explicitly set list of supported ciphers
ssl_ciphers ECDH+AESGCM:ECDH+AES256-CBC:ECDH+AES128-CBC:DH+3DES:!ADH:!AECDH:!MD5;
ssl_certificate "/etc/pki/atmloader/server.crt";
ssl_certificate_key "/etc/pki/atmloader/server.pem";
# ...
}
Notice the missing ssl in the listen parameter values.
A copy-and-paste mistake on my part when copying configuration that was originally created for a non-HTTPS port.
My server was hosted in Bluehost (Apache), the certificate was working fine. Now, I'm using Google Cloud for multiple pages in NodeJS on different port using proxy_pass. I am trying to configure the SSL but I have problems. I was looking for similar questions, but it still shows the same error. I created the key file following this link
/var/log/nginx/error.log:
2015/07/08 10:47:20 [emerg] 2950#0: SL_CTX_use_PrivateKey_file("/etc/nginx/ssl/domain_com/domain_com.key") failed (SSL: error:0B080074:x509 certificate routines:X509_check_private_key:key values mismatch)
When I put on console:
openssl rsa -noout -modulus -in domain_com.key shows me this:
Modulus=D484DD1......512 characters in total......5A8F3DEF999005F
openssl x509 -noout -modulus -in ssl-bundle.crt:
Modulus=B1E3B0A.......512 characters in total......AFC79424BE139
This is my Nginx setup:
server {
listen 443;
server_name www.domain.com;
ssl_certificate /etc/nginx/ssl/domain_com/ssl-bundle.crt;
ssl_certificate_key /etc/nginx/ssl/domain_com/domain_com.key;
ssl on;
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
ssl_prefer_server_ciphers on;
access_log /var/log/nginx/domain_com.access.log;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://localhost:8086;
proxy_read_timeout 90;
proxy_redirect http://localhost:8086 https://www.domain.com;
}
}
The problem may occur in case of wrong concatenation order. You tried:
cat www_example_com.crt COMODORSADomainValidationSecureServerCA.crt COMODORSAAddTrustCA.crt AddTrustExternalCARoot.crt > ssl-bundle.crt
Which looks correct, but concatenation usually require to eliminate extra download from root CA, therefore Nginx creator said:
Browsers usually store intermediate certificates which they receive
and which are signed by trusted authorities, so actively used browsers
may already have the required intermediate certificates and may not
complain about a certificate sent without a chained bundle.
The official docs explicitly says:
If the server certificate and the bundle have been concatenated in
the wrong order, nginx will fail to start and will display the error
message:
SSL_CTX_use_PrivateKey_file(" ... /www.example.com.key") failed
(SSL: error:0B080074:x509 certificate routines:
X509_check_private_key:key values mismatch)
because nginx has tried to use the private key with the bundle’s first
certificate instead of the server certificate.
So to solve the problem please try:
Attach www_example_com.crt to ssl_certificate Nginx config key
Download latest Comodo CA certificates SHA2 from official web page and try one more time to concatenate the bundle
I get this error when I try to get page with client key and certificate using this command:
curl -v -s --key /home/dmitry/Downloads/client_cert/client.mysite.key --cert /home/dmitry/Downloads/client_cert/client.mysite.crt https://mysite.com/api/login/
Here's what I see in nginx logs:
2014/12/08 06:30:55 [crit] 13087#0: *404 SSL_do_handshake() failed (SSL: error:14094085:SSL routines:SSL3_READ_BYTES:ccs received early) while SSL handshaking, client: xxx.xxx.xxx.xxx, server: 0.0.0.0:443
And here is part of my nginx.conf:
server {
listen 443 ssl;
ssl_certificate /home/mysite/conf/dev/ssl/com.mysite.crt;
ssl_certificate_key /home/mysite/conf/dev/ssl/com.mysite.key;
ssl_client_certificate /home/mysite/conf/dev/ssl/com.mysite.crt;
ssl_verify_client optional;
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
server_name mysite.com www.mysite.com;
access_log /home/mysite/logs/nginx_access.log;
error_log /home/mysite/logs/nginx_error.log;
location /api/{
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_set_header SSL-client-serial $ssl_client_serial;
proxy_set_header SSL-client-dn $ssl_client_s_dn;
proxy_set_header SSL-client-verify $ssl_client_verify;
if ($ssl_client_verify != SUCCESS) {
return 403;
break;
}
}
}
Here are the commands I've used to create client cert:
openssl req -out client.mysite.csr -new -newkey rsa:2048 -nodes -keyout client.mysite.key
openssl x509 -req -days 3650 -in client.mysite.csr -CA com.mysite.crt -CAkey com.mysite.key -set_serial 01 -out client.mysite.crt
What could be wrong here? Should I use some other certificate as CA for my client cert than server cert?
UPDATE:
When I do
openssl verify -CAfile com.mysite.crt client.mysite.crt
I get:
error 20 at 0 depth lookup:unable to get local issuer certificate
First of all, enable debug log in nginx.conf:
error_log logs/error.log debug;
And restart nginx. Then repeat the request and check the log file. Find the first line with verify:0:
2019/12/05 22:34:50 [debug] 5980#9776: *17 verify:0, error:20, depth:0, subject:"/CN=...", issuer:"/CN=..."
Here you see error:20. The error code comes from OpenSSL. Here you can find the constant name by code and here the corresponding description by constant name.
Alternatively you can verify the certificate using openssl command line tool:
openssl verify -CAfile ca.crt client.crt
To verify it as the server sees it, ca.crt has to be the file listed in ssl_client_certificate or ssl_trusted_certificate directive in nginx.conf.
To verify the certificate on its own, ca.crt has to be the certificate that was used to sign client.crt. If it is self-signed, it'll be client.crt itself (client.crt will be twice in a row).
If you're getting error 20 specifically and your client certificate is self-signed, you might have encountered this bug. To fix it you should either drop keyUsage from your certificate entirely or add keyCertSign to the list. To verify whether you've stumbled upon it, check whether Key Usage is listed in X509v3 extensions: section in the output of the following command:
openssl x509 -in client.crt -text -noout
The certificate I used to sign another one was not CA so it simply could not be verified, so that's why I had this error from openssl verify command:
error 20 at 0 depth lookup:unable to get local issuer certificate
If you're not CA then obviously there's nothing you can do about it.
ccs received early
Looks like a fallout from fixes for CVE-2014-0224. Since patches seems to be available check that your system is up-to-date or report the bug to your distributor.
More details might be available if you would add information about the server system you are running, especially which OS, which version of OpenSSL and which patches.
In my case I mistakenly downloaded 'cloudflare.crt' file from digital ocean's website which has older certificate and that wasted quite a bit of my time.
As their tutorial shows up in the google search.
wrong certificate from digital ocean
link to correct certificate
I have A nice working way. First before Creating pointing domain i.e
server_name api.example.com;
location / {
proxy_pass "http://example.com:9191";
}
create a sub domain of api.domain.com in your cpanel then now locate your crt files here
/var/cpanel/ssl/apache_tls/api.domain.com
you will find combined file done now put combine file i.e
ssl_certificate /var/cpanel/ssl/apache_tls/api.domain.com/combined;
then ssl you will find it under cpanel ssl/tsl->install ssl
You can locate where your ssl file are via google
your end ssl configuration will be like this
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name api.example.com;
location / {
proxy_pass "http://example.com:9191";
}
location /socket.io/ {
proxy_pass "http://example.com:9191";
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400;
}
location /engine.io/ {
proxy_pass "http://example.com:9191";
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400;
}
ssl_certificate /var/cpanel/ssl/apache_tls/api.domain.com/combined;
ssl_certificate_key /var/cpanel/ssl/system/certs/crashgame/private.key;
}
Please have your Private key in path where you can locate