nginx reverse proxy sends all traffic to first defined server - nginx

I have multiple servers running on the same host. I am trying to configure nginx to route traffic based on the server_name, but all traffic is sent to the first defined server.
I have two urls:
example.domain.net
domain.net
which I have configured nginx to proxy with configuration:
server {
listen 3978;
listen [::]:3978;
server_name example.domain.net:3978 example.domain.net:3978;
location / {
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass https://127.0.0.1:8443;
}
}
server {
listen 3978;
listen [::]:3978;
server_name domain.net:3978 www.domain.net:3978;
location / {
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass https://127.0.0.1:8020;
}
}
But all traffic to both example.domain.net:3978 and domain.net:3978 is being sent to whichever server is defined first in the file (in this case example.domain.net)
I've seen other examples where this worked like This post. Is this possible with one having a subdomain and another not?
I am using nginx version 1.18.0 with the default nginx.conf on Ubuntu 18.04

server_name should not have ports. Try removing :3978 from the server_name.
Because you have the ports, the hostname does not match any of the server_name. So, the entire traffic is sent to the first server which is considered as a default for no matches.

Related

Nginx upstream and listen of the same port

I have configured nginx on an EC2 instance.
I am running rabbitmq-management which is running on port 15672 and is accessible using the IP address of the instance.
http://ip-address:15672
I do not want to allow access using the IP address and want to use my domain but using the same port as
http://utils.example.com:15672
For that, I tried to configure the nginx server with configuration
upstream rabbitmq_server {
server localhost:15672;
}
server {
listen 15672 ssl;
server_name utils.example.com;
location / {
proxy_pass http://rabbitmq_server/;
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-Protocol $scheme;
}
}
But, this is giving error on starting the nginx server as
[emerg] 7476#7476: bind() to 0.0.0.0:15672 failed (98: Address already in use)
When I change the port to listen 15673, it works and is accessible using the domain also but is accessible using the IP address also.
How can I use the same internal IP on which application is running to be accessible from http://utils.example.com?
How can I disable direct access from the IP address and restrict access to domain/sub-domain only?
You could use an IF and check the $host variable inside the location, you can find the IF guide for nginx here
https://www.nginx.com/resources/wiki/start/topics/depth/ifisevil/
Result would be similar to this one
upstream rabbitmq_server {
server localhost:15672;
}
server {
listen 15672 ssl;
server_name utils.example.com;
location / {
if ($host = utils.example.com) {
proxy_pass http://rabbitmq_server/;
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-Protocol $scheme;
}
}
}
1)How can I use the same internal IP on which application is running to be accessible from http://utils.example.com?
You can't have those 2 applicacions (nginx and rabbit) listening to the same port.
sending a petition to ip: http://utils.example.com:15672 and http://ip:15672 is the same (not exactly, but for the example it will work).
My recomendation:
Change rabbitmq port to another one, lets say 15673. and set the nginx config like this:
upstream rabbitmq_server {
server localhost:15673;
}
server {
listen 15672 ssl;
server_name utils.example.com your_ip_numbers;
location / {
proxy_pass http://rabbitmq_server/;
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-Protocol $scheme;
}
}
Like this, both your_ip:15672 and utils.example.com:15672 will go through nginx to be proxied to rabbitmq.
2) How can I disable direct access from the IP address and restrict access to domain/sub-domain only?
Take out "your_ip_numbers" from the server_name directive if you are going to use the recomendation and block any access to port 15673 in the firewall. Localhost proxies are not considered as a normal connection by most firewalls.
And if you only have proxy to rabbitmq to the server bracket of server_name utils.example.com; that's already a way to filter only this subdomain connections to rabbitmq.
If I have not expressed myself correctly, ask me in the comments what I'm refering to, I'd be glad to answer
Edit:
For the ip not to be proxy_passed, creating another default_server bracket in the same port (it's nginx so they don't collide) will send the ip there.
server {
listen 15672 ssl default_server;
server_name _;
return 418; #(or really any code you like)
}
Hope I helped.

How can I configure access from external ip to internal ip on GCP through nginx reverse proxy?

Can't connect to application through External IP.
I started gerrit code review application on GCP's vm instance(CentOS 7).
It works on http://localhost:8080 and I can't connect to it through external IP. Also I tried to create NGINX reverse proxy, but probably my configuration is wrong. By the way after installing NGINX, the starter page were shown on external ip.
# nginx configuration /etc/nginx/conf.d/default.conf
server {
listen 80;
server_name localhost;
auth_basic "Welcomme to Gerrit Code Review Site!";
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
}
}
gerrit.config
[httpd]
listenUrl = proxy-http://127.0.0.1:8080/
You use localhost as a server_name. I think that may cause conflict, because you connect to your server externally. You don't need server_name, cause you are going connect to your server by ip. And I recommend you enable logs in your nginx config. It will help you with bug fixing.
I recommend you try this config:
server {
listen 80;
access_log /var/log/nginx/gerrit_access.log;
error_log /var/log/nginx/gerrit_error.log;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
}
}
add a line in /etc/hosts
127.0.0.1 internal.domain
Update proxy config
proxy_pass http://internal.domain:8080;
It works with me

Nginx preserve $request_uri

I'm not sure if the behavior I want is actually possible natively with nginx but here goes.
I have a server running on port 81 with the following nginx config:
CONFIGURATION OF SERVER1 NGINX
server {
listen 81;
server_name SERVER_DNS_NAME;
location /server1 {
proxy_pass http://127.0.0.1:8084/;
proxy_set_header Host $host;
}
location / {
proxy_pass http://127.0.0.1:8084;
proxy_set_header Host $host:$server_port;
}
}
I have another server running on port 82 with similar configuration. Now what'd i'd like to do is be able to visit them both from port 80 with just different uris.
For example: URL/server1 would take me to the first server, and URL/server2 would take me to the second.
CONFIGURATION OF NGINX LISTENING ON PORT 80
server {
listen SERVER_IP:80;
location /server1{
proxy_set_header Host $host;
http://SERVER_IP:81;
}
location /server2 {
proxy_pass http://SERVER_IP:82;
proxy_set_header Host $host;
}
This works fine when I go to URL/server1. I am successfully routed to the main page on server1. However as soon as I click any of the links present on the page on server1 I get a 404. This is because the site tries to go to URL/some_subdir_of_server1 (for which there is no mapping) rather than doing URL/server1/some_subdir_of_server1. Is this behavior doable? If so how?
Thanks!
Be careful with trailing slashes: in your example, you have
proxy_pass http://SERVER_IP:81/; which will set the proxy URL to root /

nginx reverse proxy to backend running on localhost

EDIT: It turns out that the my setup below actually works. Previously, I was getting redirections to port 36000 but it was due to some configuration settings on my backend application that was causing it.
I am not entirely sure, but I believe I might be wanting to set up a reverse proxy using nginx.
I have an application running on a server at port 36000. By default, port 36000 is not publicly accessible and my intention is for nginx to listen to a public url, direct any request to the url to an application running on port 36000. During this entire process, the user should not know that his/her request is being sent to an application running on my server's port 36000.
To put it in more concrete terms, assume that my url is http://domain.somehost.com/
Upon visiting http://domain.somehost.com/ , nginx should pick up the request and redirect it to an application already running on the server on port 36000, the application does some processing, and passes the response back. Port 36000 is not publicly accessible and should not appear as part of any url.
I've tried a setup that looks like:
server {
listen 80;
server_name domain.somehost.com
location / {
proxy_pass http://127.0.0.1:36000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
and including that inside my main nginx.conf
However, it requires me to make port 36000 publicly accessible, and I'm trying to avoid that. The port 36000 also shows up as part of the forwarded url in the web browser.
Is there any way that I can do the same thing, but without making port 36000 accessible?
Thank you.
EDIT: The config below is from a working nginx config, with the hostname and port changed.
You need to may be able to set the server listening on port 36000 as an upstream server (see http://nginx.org/en/docs/http/ngx_http_upstream_module.html).
server {
listen 80;
server_name domain.somehost.com;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://localhost:36000/;
proxy_redirect http://localhost:36000/ https://$server_name/;
}
}

How do I set up nginx to serve data from a port?

I have nginx serving a page on port 80.
server {
listen 80;
server_name .example.com;
root /var/www/docs;
index index.html;
}
I also have a service running a server on port 9000. How do I set up a virtual directory in nginx (such as /service) to serve whatever is on port 9000? I am unable to open other ports, so I would like to serve this through some kind of virtual directory on port 80.
Start with that (but you definetly will need more directives to make your server normally answering on this subdirectory):
location /something {
proxy_pass http://localhost:9000/;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
}

Resources