client authentication when using nginx proxy_pass - nginx

My question is about nginx directive "proxy_pass".
I have an http server and I need to redirect requests using https.
I'm using the following statement:
proxy_pass https://secure.server
In wireshark I see that there is a SSL handshake, but client (nginx proxy_pass https:) did not send certificate on server's SSL certificate request.
Verifying client certificate is necessary by server. How can I force proxy_pass to send client certificate when using https ?
Below is part of nginx.conf configuration file:
server {
listen 8888;
server_name _;
error_page 405 =200 $uri;
ssl_certificate /usr/local/cert.pem;
ssl_certificate_key /usr/local/cert.pem
ssl_client_certificate /usr/local/ca.cer;
location ~ /uri/(.+) {
proxy_pass https://secure.server;
break;
}
}

You need to enable SSL client certificate verification.
Add this under the other SSL configurations:
ssl_verify_client on;
See more information here.

I'm looking for the same solution as well.
I found SEnginx, which has a module called "Proxy HTTPS Client Certificate". From the description it seems that is should allow for client certificates, but I could not get it to work for me. The backend server simply would not prompt the client for a certificate.
Following is the link to SEnginx.
Also: Here is a possible explanation as to why this might not be possible.

During ssl handshake, the server will send "client certificate ca names". (ie) The server will accept the client certificates only from those CAs. Client will send send client certificate only if it has a cert signed by those CA.
So in your case, verify
1. The CA names send by server for client cert request. This will be the CAs you have configured in the truststore of the server. (ie) During ssl handshake look for CertificateRequest message
Make sure you client cert is signed by one of those CA
Best option is to verify with curl, both your client and server certificates are configured properly
curl -vvv --cert /usr/local/cert.pem https://secure.server
If you are not able to figure out with the curl output, please paste the curl output

Related

Error: SSL Misconfiguration (Your connection to this site is not secure)

Exact error I am getting on browser:
This server could not prove that it is XXX.XX.XXX.XXX; its security certificate is from newDomain.live. This may be caused by a misconfiguration or an attacker intercepting your connection.
NGINX Config:
server {
# listen on port 443 (https)
listen 443 ssl;
server_name _;
# location of the self-signed SSL certificate
ssl_certificate /home/ubuntu/certs/server.pem;
ssl_certificate_key /home/ubuntu/certs/server.key;
# write access and error logs to /var/log
access_log /var/log/app_access.log;
error_log /var/log/app_error.log;
location / {
# forward application requests to the gunicorn server
proxy_pass http://localhost:8000;
proxy_redirect 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;
}
}
What I have done:
Ran openssl req –new –newkey rsa:2048 –nodes –keyout server.key –out server.csr in terminal
Copied server.csr from server to SSL provider as it asked for CSR from web hosting
SSL Certificate issued by provider have two fields 1. Server Certificate 2. CA Certificates(intermediate and root)
At this moment I have checked but it was still unverified and couldnt establish https connection.
Then, I deleted the server.csr file from server and created a new one by copying "1. Server Certificate" given by SSL provider.
I am using AWS EC2 instance and running NGINX as reverse proxy. How can I fix this misconfiguration of SSL?
The certificate returned by the server does not match the name in the URL. Based on this description you've created a certificate for newDomain.live but you are trying to access the site using and IP address xxx.xxx.xxx.xxx, which is not the domain you created.
If the domain is not a valid domain (i.e. no DNS entry you can add the domain to your local hosts file, with the IP as the target then put the domain name in your browser as the address. This will redirect to the IP defined in your hosts file.
For more information, update host in windows, update host in linux.
Solution: access the website using the same domain name that you registered the certificate for.
See this thread for details of a similar error you are experiencing and this thread for details of self signed certificate errors.
An alternative approach:
This approach does not solve your NGINX problem.
Instead of using NGINX, why don't you front your EC2 instance with an Application Load Balancer.
Then use a certificate generated by AWS Certificate Manager (ACM), not only are the certificates free but:
they are signed by Amazon, so the certificate is trusted, if you use
DNS validation the certificates are automatically rotated when they
expire.
You can find out how to do this here.
You can restrict traffic to originate from the load balancer using security groups, and you can front the load balancer with Amazon CloudFront.
ACM best practice information is available here.

NGNIX reverse proxy with client certificate

I have front end serverA and back end serverB. the actual application is hosted on serverB. When the client makes call to API, serverB will have to authenticate using client certificate that is sent by client.
We have installed Ngnix in serverA to proxy_pass the traffic received from clients to serverB.
when the client make call to serverA with client certificate, the client certificate is not sent by Ngnix to serverB and due to this serverB reject the request from client.
Is there any way we can redirect the request to serverB along with client certificate that is originally sent by clients?
Below is my Ngnix configuration.
If Ngnix is not capable of doing this, is there any other opensource tool avaialable with this functionality?
server {
listen 443 ssl;
server_name localhost;
ssl_certificate cert.pem;
ssl_certificate_key cert.pem;
ssl on;
location / {
root html;
index index.html index.htm;
proxy_pass "https://localhost:8099";
}
}
Sorry, maybe late for that, but hope it helps.
You can proxy requests with client certificate by sending the variable $ssl_client_cert in a request header when proxying to the back end serverB.

NGINX Reverse proxy response

I am using an NGINX server as a reverse proxy. The NGINX server accepts a request from an external client (HTTP or HTTPS doesn't matter) and passes this request to a backend server. The backend server returns "a" URL to the client that will have another URL that it should use to make subsequent API calls. I want this returned URL to have the NGIX host and port number instead of the backend service host and port number so that my backend server details are never exposed. For e.g.
1) Client request:
http://nginx_server:8080
2) Nginx receives this and passes it to the backend running with some functionality at
http://backend_server:8090
3) The backend server receives this request and passes another URL to the client http://backend_server:8090/allok.
4) The client uses this URL and makes another subsequent API calls.
What I want is that in step 4 in the response the "backend_server:port" is replaced by the nginx server and port from the initial request. For e.g
http://nginx_server:8080/allok
However, the response goes back as
http://backend_server:8090/allok
my nginx.conf
http {
server {
listen 8080; --> Client request port
server_name localhost;
location / {
proxy_pass http://localhost:8090; ---> Backend server port. The backend
service and NGINX will always be on the same
machine
proxy_redirect http://localhost:8090 http://localhost:8080; --> Not sure if this is
correct. Doesn't seem to do what I want to achieve
# proxy_set_header Host $host;
}
}
}
Thanks in advance
I was able to resolve it. I had to eliminate the proxy_redirect directive from the config.

Temporarily redirect https domain to http

How can I configure my NGINX conf file to temporarily redirect an https domain to the http version?
I've found ways to redirect http to https, which is more common, but not the other way around. The reason I need to do this is because I'm in the process of setting up an SSL certificate for a website and somehow, some https URLs are being indexed, on which some assets don't load without the certificate. Thank you in advance!
The problem with redirecting https to http is that you still need a certificate for https - so if you want to redirect because you do not have the certificate yet, this will probably not solve anything, because the secure https connection happens before the redirect.
Otherwise redirecting from https to http works the same as the other way round - it could look something like this: (server block in your http config)
server {
listen 443 ssl;
server_name yourdomain.com;
ssl_certificate /certificate.pem;
ssl_certificate_key /certificate.key;
return 302 http://$host$request_uri;
}
You just need to adjust the domain name and the certificate paths/filenames.

How to configure nginx to proxy another service serving http and https on different ports?

Use case:
Using nginx as a frontend for several websites / services running on both 80 and 443 (several virtual hosts).
Having service x running on localhost that serves http:8090 and https:8099
How do I need to configure nginx so people can access using only the name, without specifying the port.
This a fairly normal setup. Configure the hosts served directly on Nginx as normal. Since they need to listen on both 80 and 443, each host entry would have this in it:
server {
listen 80;
listen 443 ssl;
}
The Nginx SSL docs has the full details.
Then proxy traffic for one server{} definition to the backend service:
server {
server_name example.com;
location / { proxy_pass http://127.0.0.1:8090; }
}
You only need one proxy connection to the backend server, either 'http' or 'https'. If the connection between the two servers is secure, you can 'http', even for connections that arrive to nginx over https. This might be appropriate if the service is on the same machine. Otherwise, all the traffic could be proxied through https if the connection between nginx and the backend server needs to be secured.
We use the following with our host:
http {
server {
server_name ~^(www\.)?(?<domain>.+)$;
listen *:80;
location / {
proxy_pass $scheme://<origin>$uri$is_args$args;
include basic-proxy-settings.conf;
}
}
server {
server_name ~^(www\.)?(?<domain>.+)$;
listen *:443 ssl;
location / {
proxy_pass $scheme://<origin>$uri$is_args$args;
include basic-proxy-settings.conf;
}
include ssl-settings.conf;
}
}
This allows our upstream proxy to talk to our origin server over HTTP when a request is made by a client for an insecure resource, and over SSL/HTTPS when a request is made for a secure one. It also allows our origin servers to be in charge of forcing redirects to secure connections, etc.
Next time, why not provide a code sample detailing what you've tried, what has worked, and what hasn't?

Resources