So I have been working on a project on a separate server for a company and now they want me to set it up for production with their SSL certificate and Key.
Here is my nginx.config file that is on the server I am working on
`
server{
listen 443;
ssl on;
ssl_certificate "/etc/pki/tls/certs/example.cer";
ssl_certificate_key "/etc/pki/tls/certs/exampleKey.pem";
#ssl_session_cache shared:SSL:1m;
#ssl_session_timeout 10m;
#ssl_ciphers HIGH:!aNULL:!MD5;
#ssl_prefer_server_ciphers on;
server_name snap.example.gov;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
proxy_pass http://localhost:80;
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 ;
proxy_set_header X-Forwarded-Proto https;
}`
I've tried to follow all the tutorials but it still won't load over 'snap.example.gov'. I really need help to get this to load over https on the 'snap.example.gov' domain. What am I doing wrong? I'm still new to this so I'm not quite sure what to do.
Thank you guys in advance.
All the world is the internet and IP addresses are but its players. How does your computer know which computer server to connect to when you type 'snap.example.gov'? The answer is, it doesn't! Thus began the Domain Name System which affords your operating system the ability to go on the internet and query a series of well known servers that do know the IP address of every registered domain name on the internet. DNS knows that the IP address of stackoverflow.com is 151.101.65.69. Your computer doesn't.
So, you have to register your server's domain name with those DNS servers and tell them what the IP address to access your site is. The fee for this service is as low as $11 or so but can be up to $50 assuming the name is available at all. example.gov, for example, is owned by the GSA of the United States government so you are not likely going to be able to register that name.
There are a large number of domain name registrars and stackoverflow does not really like us to recommend one but searching for that will bring up some good ones.
Related
I'm learning how to build and host my own website using Python and Flask, but I'm unable to make my website work as I keep getting an infinite redirect loop when I try to access my website through my domain name.
I've made my website using Python, Flask, and Flask-Flatpages. I uploaded the code to GitHub and pulled it onto a Raspberry Pi 4 that I have at my house. I installed gunicorn on the RasPi to serve the website and set up two workers to listen for requests. I've also set up nginx to act as a reverse proxy and listen to requests from outside. Here is my nginx configuration:
server {
if ($host = <redacted>.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
# listen on port 80 (http)
listen 80;
server_name <redacted>.com www.<redacted>.com;
location ~ /.well-known {
root /home/pi/<redacted>.com/certs;
}
location / {
# redirect any requests to the same URL but on https
return 301 https://$host$request_uri;
}
}
server {
# listen on port 443 (https)
listen 443;
ssl on;
server_name <redacted>.com www.<redacted>.com;
# location of the SSL certificate
ssl_certificate /etc/letsencrypt/live/<redacted>.com/fullchain.pem; # m$
ssl_certificate_key /etc/letsencrypt/live/<redacted>.com/privkey.pem; #$
# write access and error logs to /var/log
access_log /var/log/blog_access.log;
error_log /var/log/blog_error.log;
location / {
# forward application requests to the gunicorn server
proxy_pass http://localhost:8000;
proxy_redirect off;
proxy_set_header X_Forwarded_Proto $scheme;
proxy_set_header Host $host;
location /static {
# handle static files directly, without forwarding to the application
alias /home/pi/<redacted>.com/blog/static;
expires 30d;
}
}
When I access the website by typing in the local IP of the RasPi (I've set up a static IP address in /etc/dhcpcd.conf), the website is served just fine, although it seems like my browser won't recognize the SSL certificate even though Chrome says the certificate is valid when I click on Not Secure > Certificate next to the .
To make the website public, I've forwarded port 80 on my router to the RasPi and set up ufw to allow requests only from ports 80, 443, and 22. I purchased a domain name using GoDaddy, then added the domain to CloudFlare by changing the nameservers in GoDaddy (I'm planning to set up cloudflare-ddns later, which is why I added the domain to CloudFlare in the first place). As a temporary solution, I've added the current IP of my router to the A Record in the CloudFlare DNS settings, which I'm hoping will be the same for the next few days.
My problem arises when I try to access my website via my public domain name. When I do so, I get ERR_TOO_MANY_REDIRECTS, and I suspect this is due to some problem with my nginx configuration. I've already read this post and tried changing my CloudFlare SSL/TLS setting from Flexible to Full (strict). However, this leads to a different problem, where I get a CloudFlare error 522: connection timed out. None of the solutions in the CloudFlare help page seem to apply to my situation, as I've confirmed that:
I haven't blocked any CloudFlare IPs in ufw
The server isn't overloaded (I'm the only one accessing it right now)
Keepalive is enabled (I haven't changed anything from the default, although I'm unsure whether it is enabled by default)
The IP address in the A Record of the DNS Table matches the Public IP of my router (found through searching "What is my IP" on google)
Apologies if there is a lot in here for a single question, but any help would be appreciated!
I only see one obvious problem with your config, which is that this block that was automatically added by certbot should probably be removed:
if ($host = <redacted>.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
Because that behavior is already specified in the location / {} block, and I think the Certbot rule may take effect before the location ~ /.well-known block and break that functionality. I'm not certain about that, and I don't think that would cause the redirects, but you can test the well-known functionality yourself by trying to access http://yourhost.com/.well-known and seeing if it redirects to HTTPS or not.
On that note, the immediate answer to your question is, get more information about what's happening! My next step would be to see what the redirect loop is - your browser may show this in its network requests log, or you can use a command-line tool like curl or httpie or similar to try to access your site via the hostname and see what requests are being made. Is it simply trying to access the same URL over and over, or is it looping through multiple URLs? What are they? What does that point at?
And as a side note, it makes sense that Chrome wouldn't like your certificate when accessing it via IP - certificates are tied to one or more hostnames, so when you're accessing it over an IP address, the hostname doesn't match, so Chrome is probably (correctly) pointing that out and warning you that you're not at the hostname the certificate says you should be at.
I have a use-case where upstream servers will trust different CAs. This is mainly happening during transition period and hence I would like to have my nginx proxy to the upstream servers by trying two different CA certs.
Currently I have an idea of doing something like:
location /upstream1 {
proxy_pass https://$http_host$uri;
proxy_ssl_certificate /home/keys/cert.pem
proxy_ssl_certificate_key /home/keys/key.pem
proxy_ssl_trusted_certificate /home/keys/trust.pem
proxy_intercept_errors on;
recursive_error_pages on;
error_page 495 496 = #use_cert2
}
location #use_cert2 {
proxy_pass https://$http_host$uri;
proxy_ssl_certificate /home/keys/cert2.pem
proxy_ssl_certificate_key /home/keys/key2.pem
proxy_ssl_trusted_certificate /home/keys/trust2.pem
}
Is this the most elegant way to have the logic of "try to use this certificate to proxy to upstream server. If the server doesn't like it, then use this different certificate".
Also it calls #use_cert2, does it preserve any rewrite that happened in the previous call block?
Apology in advance if the question does not have enough information.
Thank you for reading the post!
I have done some resarch for this matter and there are some unaswered question regarding my issue, however I managed to solve half of what is needed (thanks to people on the site).
Scenerio:
I have Nginx as a reverse proxy in internal corporate network. I need to pass traffic to Internet behind corporate proxy.
Half of the solution:
To achive this, following works fine:
server {
listen 80;
server_name myhost.com;
location / {
proxy_set_header Host google.com;
proxy_pass http://corporateproxy:9999/;
}
}
However, above solution does not use SSL between corporate proxy and google.com. Do you have any idea how to add SSL to this?
I have tried adding protocol or port to header but it is not working this way.
I cannot modify anything on the corporate proxy. It should work like this: the URL being accessed is with https it will be redirected to https; http to http. Unfortunatelly header that contains only dns name is treated as http request.
Unfortunatelly the simplest solution does not work because nginx does not respect http_proxy settings on RedHat Machine:
server {
listen 80;
server_name myhost.com;
location / {
proxy_pass https://google.com/;
}
}
Any help will be highly appreciated.
We are using MUP for Meteor deployment to AWS. Couple of weeks ago we got excited that we can now switch to a free cert, thanks to Letsencrypt and Kadira. Everything was working very nicely, until I realized in the logs that client IP is no longer being passed through the proxy... No matter what I do, I see 127.0.0.1 as my client IP. I was trying to get it in methods using this.connection.clientIP or headers package.
Well, after doing much research and learning in-depth how stub and nginx work, I came to conclusion that this was never working.
The best solution I came up with is to use proxy_protocol as described by Chris, but I could not get it to work.
I have played with settings of /opt/stud/stud.conf and attempted to turn write-proxy and proxy-proxy settings on.
This is what my nginx config looks like:
server {
listen 80 proxy_protocol;
server_name www.example.com example.com;
set_real_ip_from 127.0.0.1;
real_ip_header proxy_protocol;
access_log /var/log/nginx/example.access.log;
error_log /var/log/nginx/example.error.log;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto http;
}
}
Here is what my headers look like on production EC2 server:
accept:"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"
accept-encoding:"gzip, deflate, sdch"
accept-language:"en-US,en;q=0.8"
cache-control:"no-cache"
connection:"upgrade"
host:"127.0.0.1:3000"
pragma:"no-cache"
upgrade-insecure-requests:"1"
x-forwarded-for:"127.0.0.1"
x-forwarded-proto:"http"
x-ip-chain:"127.0.0.1,127.0.0.1"
x-real-ip:"127.0.0.1"
So, the questions of the day. Using MUP with SSL, is there a way to get a pass-though client IP address?
I know you said you have tried using headers, but you may give it another shot and see if you can get something this way. I was having alot of problems with x-forwarded-for counts not staying consistent, but if I pull from the header chain, [0] is always the client IP.
Put this code in your /server folder:
Meteor.methods({
getIP: function() {
var header = this.connection.httpHeaders;
var ipAddress = header['x-forwarded-for'].split(',')[0];
return ipAddress;
}
});
In your browser console:
Meteor.call('getIP', function(err, result){
if(!err){
console.log(result);
} else {
console.log(err);
}
};
See what you get from that response. If that works, you can just call the method on Template.rendered or whenever you need the IP.
Otherwise, I'm pretty sure you should be able to set the IP to an arbitrary header in your nginx conf and then access it directly in the req object.
By the way, in the nginx config you included, I think you need to use real_ip_header X-Forwarded-For; so that real_ip will use that header to locate the client IP, and you should also set real_ip_recursive on; so that it will ignore your trusted set_real_ip_from
Alright, so after a sleepless night and learning everything I could about the way STUD and HAProxy protocol works, I came to a simple conclusion it's simply not supported.
I knew I could easily go back to have SSL termination at Nginx, but I wanted to make sure that my deployment has automation as MUP.
Solution? MUPX. The next version of MUP, but still in development. It uses Docker and has SSL termination directly at Nginx.
So there you have it. Lesson? Stable is not always a solution. :)
In the following scenario,
[client]---https--->[Nginx]---http--->[app server]
How (and what) would I pass down to the app server to uniquely identify the certificate? That is, Nginx validates the certificate, but app server doesn't see it. I need to distinguish between users at the app server, so they can't impersonate each other.
You could adapt the same technique as what's described in this question for Apache Httpd. You'd need the Nginx equivalent of something like:
RequestHeader set X-ClientCert ""
RequestHeader set X-ClientCert "%{SSL_CLIENT_CERT}s"
I haven't tried, but the documentation for the Nginx SSL module has a section about "Embedded Variables". More specifically:
$ssl_client_cert returns the client certificate in the PEM format for an established SSL connection, with each line except the first prepended
with the tab character; this is intended for the use in the
proxy_set_header directive;
This looks like what you need with a reverse-proxy setting, like the one you have.
Note that it's very important to clear this header on its way in, otherwise clients could just set the headers themselves and use any certificate they like.
How you then want to check this in your application server depends on the platform you're using. In Java, for example, you could write a Filter (or a Tomcat Valve) that sets the parameter in the request from this custom HTTP header.
It sounds like you want to use Nginx for SSL termination, but you want the backend servers to be able to tell with the original request was over HTTPS or HTTP.
I think something this could work:
server {
ssl on;
listen 443;
add_header X-Forwarded-Proto https;
proxy_pass ...
}
# If you need insecure requests as well
server {
listen 80;
add_header X-Forwarded-Proto http;
proxy_pass ...
}
Then your app server can check the value of the X-Forwarded-Proto header.
This is the same design pattern that Amazon Web Services uses for terminating SSL at their Elastic Load Balancers. They also set the X-Forwarded-Proto header for backend servers to check.