client ip behind nginx reverse proxy - nginx

I'm running an nginx reverse proxy to be able to run multiple servers behind my firewall. I noticed on my mail server the error log is filled with "failed login from < local ip of nginx >" and I was wondering how can I set it so I get the remote IP of the person/bot that is trying to login so I might use that information for auto blocking those addresses (for example)?
This is my current config:
server {
listen 8443 ssl http2;
server_name mail.domain.com;
location / {
proxy_set_header Host $host;
proxy_pass https://<internal ip>/;
client_max_body_size 0;
proxy_connect_timeout 3600;
proxy_send_timeout 3600;
proxy_read_timeout 3600;
send_timeout 3600;
}
}

I think you're looking for one of these
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
you can add these to http, server or location block and read the header in your app to filter the request

Just found out my mail server (Kerio) does nothing with the information forwarded by the reverse proxy, so the only thing I can do is hope for an update that does.

Related

nginx reverse proxy for application

I use nginx for reverse proxy with domain name. I've some application publish on IIS and i want to proxy different location name for each application.
For example;
Domain name on nginx :
example.com.tr
application end points for app:
1.1.1.1:10
1.1.1.2:10
upstream for app in nginx.conf:
upstream app_1 {
least_conn;
server 1.1.1.1:10;
server 1.1.1.2:10;
}
server {
listen 443 ssl;
server_name example.com.tr;
proxy_set_header X-Forwarded-Port 443;
ssl_certificate /etc/cert.crt;
ssl_certificate_key /etc/cert.key;
location /app_1/ {
proxy_pass http://app_1/;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-REAL-SCHEME $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
access_log /etc/nginx/log/access.log;
error_log /etc/nginx/log/error.log;
}
}
When I try to access example.com.tr/app_1/ , I can access application but not all data.
I inspected this site and so many requests of application were failed.
All requests sended to example.com.tr/uri instead of example.com.tr/app_1/uri. How can I fix this ?
thanks,
You need a transparent path proxy setup. Means NGINX should use the requested URI without removing the matched location from it.
proxy_pass http://app_1;
Remove the tailing slash to tell NGINX not to do so. Using an upstream definition is great but make sure you apply keepalive.

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.

nginx proxy configuration to server with dynamic ip addresses

I am working on AWS and using an EC2 instance for CI operations and more particularly for Jenkins. This server lies behind an nginx server which is used as a proxy for requests to ci.domain.com
Everything is working fine until a failure occurs on the CI server.
Once that happens, another instance boots up, upserts its IP to the DNS service pointing the new IP to ci.domain.com
The problem is that I need to restart the nginx service in order to discover the CI server again. Before that I get 5xx Bad Request or Timeout responses.
Below is part of my nginx configuration concerning the particular upstream server:
upstream jenkins {
server ci.domain.com max_fails=3 fail_timeout=100s;
}
server {
listen 80;
server_name ci.domain.com;
location / {
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Connection "";
proxy_pass http://jenkins;
proxy_read_timeout 300;
proxy_send_timeout 300;
proxy_connect_timeout 300;
# Required for new HTTP-based CLI
proxy_http_version 1.1;
proxy_request_buffering off;
}
}

How to load balance wso2 1.9.0 with NGINX 1.6.2

I'm trying to load balance API Manager 1.9.0 with a front-end NGINX 1.6.2 load balancer. I have 2 servers:
Server A (xxx.xxx.xxx.xx1 and xxx.xxx.xxx.x11) - Public and Private IPs
Server B (xxx.xxx.xxx.xx2 and xxx.xxx.xxx.x22) - Public and Private IPs
API Manager 1.9.0 and all four components are installed and started on server B.
I stalled NGINX on Server A which also has API Manager 1.9.0 installed and running in worker mode only. The NGINX software installed in /opt/rh/nginx16/root/etc/nginx. I added the following configuration files to /opt/rh/nginx16/root/etc/nginx/conf.d and successfully started the service:
(am.http.conf)
upstream xxx.xxx.xxx.x11
server xxx.xxx.xxx.x11:9763
server xxx.xxx.xxx.x22:9763
server
listen 80
server_name xxx.xxx.xxx.x11
location /
proxy_set_header X-Forwarded-Host $host
proxy_set_header X-Forwarded-Server $host
proxy_set_header X-Forwarded-For
$proxy_add_x_forwarded_for
proxy_set_header Host $http_host
proxy_read_timeout 5m
proxy_send_timeout 5m
proxy_pass http://xxx.xxx.xxx.x11
(am.https.conf)
upstream xxx.xxx.xxx.1
server xxx.xxx.xxx.xx1:9443
server xxx.xxx.xxx.xx2:9443
server
listen 443
server_name xxx.xxx.xxx.xx1
ssl on
ssl_certificate /opt/rh/nginx16/root/etc/nginx/ssl/wrk.crt
ssl_certificate_key /opt/rh/nginx16/root/etc/nginx/ssl/wrk.key
location /
proxy_set_header X-Forwarded-Host $host
proxy_set_header X-Forwarded-Server $host
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for
proxy_set_header Host $http_host
proxy_read_timeout 5m
proxy_send_timeout 5m
proxy_pass https://xxx.xxx.xxx.xx1
(mgt.am.https.conf)
server
listen 443
server_name xxx.xxx.xxx.xx2
ssl on
ssl_certificate /opt/rh/nginx16/root/etc/nginx/ssl/mgt.crt
ssl_certificate_key /opt/rh/nginx16/root/etc/nginx/ssl/mgt.key
location /carbon
proxy_set_header X-Forwarded-Host $host
proxy_set_header X-Forwarded-Server $host
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for
proxy_set_header Host $http_host
proxy_read_timeout 5m
proxy_send_timeout 5m
proxy_pass https://xxx.xxx.xxx.xx2:9443/
error_log /var/log/nginx/mgt-error.log
access_log /var/log/nginx/mgt-access.log
I made the documented changes to the axis2.xml, carbon.xml, catalina.server.xml per this document: https://docs.wso2.com/display/CLUSTER420/Clustering+the+Gateway
I'm trying to create a prototype with limited resources.
Is it ok to an IP address for the upstream server?
How do I test the configurations above?
How do I access the index.html page verify that NGINX is installed correctly?
How do I ensure that the API workers are in sync and talking to the same database?
Any help with this will be greatly appreciated!
Upstream is used to define groups of servers that can be referenced by the directives such as proxy_pass. You can use anything for that but it is a good practice to use some user friendly naming format.
Once the API Manager clustering is completed, send requests and verify whether they are served.
Access the IP address of NGINX server on browser and see whether the index.html page is loaded
Here, assume that API Worker means APIM Gateway worker:
you have to properly define datasources across all components and mount them. Then shutdown one worker and see the request are served by other worker.
Refer https://docs.wso2.com/display/CLUSTER44x/Clustering+API+Manager+1.10.0

How to set the real ip in a request going from nginx to a backend server

I have my backend servers fronted with nginx. When a user sends a request to my backend, it hits the NginX and then it is routed to the backend server. There, I publish some stats and one of them is the client IP. In my setup, its the Nginx IP which gets published as the client IP. Is there a way and a config to set the real IP of the client?
Following is my config.
server {
listen 8280;
server_name my.server.com;
location / {
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_read_timeout 5m;
proxy_send_timeout 5m;
proxy_pass http://myserver_http/;
}
access_log /mnt/var/log/nginx/myserver/access.log;
error_log /mnt/var/log/nginx/myserver/error.log;
}
in order to forward the real client IP use inside your location block:
proxy_set_header X-Real-IP $remote_addr;

Resources