How to set remote_addr to the real client IP? - nginx

I have the following nginx.conf and in the access.log I am getting as remote_addr the same IP for every request, which is the IP of my VM.
events{}
# See blow link for Creating NGINX Plus and NGINX Configuration Files
# https://docs.nginx.com/nginx/admin-guide/basic-functionality/managing-configuration-files/
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# The identifier Backend is internal to nginx, and used to name this specific upstream
upstream backend {
# BACKEND_HOST is the internal DNS name used by the Backend Service inside the Kubernetes cluster
# or in the services list of the docker-compose.
server ${BACKEND_HOST}:${BACKEND_PORT};
}
server {
listen ${NODE_PORT};
root /usr/share/nginx/html;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
location /api/ {
resolver 127.0.0.11;
#nginx will not crash if host is not found
# The following statement will proxy traffic to the upstream
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
}
However, I need to have in the remote_addr field the initial client IP. I know that I can use the variable realip_remote_addr, but I wanted to ask if there is any configuration that changes the remote_addr. Is somehow this possible?
EDIT: As I search more about that I think that it is important to mention that I use docker-compose to run the nginx as part of a frontend service. Maybe this is related to the network of docker.

Usually it is enough to add these two fields to the request header:
proxy_set_header x-real-ip $remote_addr;
proxy_set_header X-forwarded-for $proxy_add_x_forwarded_for;
See the documentation at proxy_set_header for more details.
In your case:
server {
listen ${NODE_PORT};
root /usr/share/nginx/html;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
location /api/ {
resolver 127.0.0.11;
#nginx will not crash if host is not found
# The following statement will proxy traffic to the upstream
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header x-real-ip $remote_addr;
proxy_set_header X-forwarded-for $proxy_add_x_forwarded_for;
}
}

We have to understand the importance of the field remote_addr, it tell the application server where to respond back, if you overwrite this value than the server won't pass the response to the network interface it came from. So for this use case you want to log real client IP , please refer to the below snippet, it might help:
events{}
# See blow link for Creating NGINX Plus and NGINX Configuration Files
# https://docs.nginx.com/nginx/admin-guide/basic-functionality/managing-configuration-files/
log_format logs_requested '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$request_time" "$upstream_response_time" "$pipe" "$http_x_forwarded_for"';
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# The identifier Backend is internal to nginx, and used to name this specific upstream
upstream backend {
# BACKEND_HOST is the internal DNS name used by the Backend Service inside the Kubernetes cluster
# or in the services list of the docker-compose.
server ${BACKEND_HOST}:${BACKEND_PORT};
}
server {
listen ${NODE_PORT};
access_log /var/log/nginx/access_logs.log logs_requested;
root /usr/share/nginx/html;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
location /api/ {
resolver 127.0.0.11;
#nginx will not crash if host is not found
# The following statement will proxy traffic to the upstream
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
}
In above snippet logs_requested is the log_format that is defined according to one's requirement. Client IP information can be see in http_x_forwarded_for variable, and access_log /var/log/nginx/access_logs.log logs_requested line is included in server block to log the request in this logs_requested format.

Check the Nginx documentation on setting up your access log desired format
https://docs.nginx.com/nginx/admin-guide/monitoring/logging/#access_log
Some more info:
https://docs.splunk.com/Documentation/AddOns/released/NGINX/Setupv2

Related

Hide port with gunicorn and nginx

The Flask server starts at port 5000. With gunicorn and nginx, when I typed http://localhost:80 (or http://localhost) in browser, the browser redirects to http://localhost:5000.
I added a few lines in the nginx config file
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
How can I hide port(5000 in this case) after redirection? Thanks a lot.
This is how you should structure your configuration file:
server {
# listen on port 80
listen 80;
server_name _;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
A server block is a subset of Nginx’s configuration that defines a virtual server used to handle requests of a defined type.
A location block lives within a server block and is used to define how Nginx should handle requests for different resources and URIs (the part of the request that comes after the domain name or IP address/port) for the parent server
How nginx processes a request

How can i allow all in nginx?

My website is only accessible on a certain ip address so i only can have access to it if i'm in that machine or a connection towards it
I tried adding Nginx allow all to the config but it's still not working
server {
listen 80;
server_name domain;
#Specify a charset
charset utf-8;
location /api {
satisfy any;
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://192.168.226.264:8080;
proxy_read_timeout 90;
allow all;
}
location / {
root /Users/administrator/Documents
try_files $uri /index.html;
}
}
I get this :
This site can’t be reached.
domain’s server IP address could not be found
What do i need to add to make the website accessible by all ip addresses
Try whether you domain is getting resolved using "whois" command from the terminal where you have installed the nginx server :
whois domainname
You have mentioned a "server_name domain" , is that domain resolvable from your terminal ?

Trying to proxy Jira through 2 nginx reverse proxies images and css do not load

I am trying to use nginx to reverse proxy through two proxies I have a server that handles all https traffic and a separate server runs Confluence and Jira. I have the first nginx proxy configured like
ssl on;
ssl_certificate /etc/letsencrypt/live/mydomain.com/cert.pem;
ssl_certificate_key /etc/letsencrypt/live/mydomain.com/privkey.pem;
access_log /var/log/nginx/nginx.mydomain.com.access.log;
error_log /var/log/nginx/nginx.mydomain.com.error.log;
server_name mydomain.com www.mydomain.com;
root /var/www/mydomain.com/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
location /jira {
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_pass http://jira.home.mydomain.com;
}
The second nginx proxy is configured as
listen jira.home.mydomain.com:80;
server_name jira.home.mydomain.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_pass http://localhost:8080/;
}
If I go to the second proxy directly JIRA works fine. But trying to go from external to Jira(through the first and second proxy) it doesn't load the css or images.
I am trying to use mydomain.com/JIRA to access JIRA at jira.home.mydomain.com
What am I doing wrong?
As per the official troubleshooting guide, try disabling gzip on nginx since the traffic is already encoded.
Worked for me on jira + ssl + nginx reverse proxy
Seeing other posts the following line may cause the issue:
try_files $uri $uri/ =404;

Using nginx as reverse proxy for apache and want more htaccess control

I'm using nginx in a reverse proxy configuration with apache2. I have used other, preconfigured web servers in this way and enjoyed complete control over redirects from an .htaccess file.
My current configuration does not allow for this. First, I'll explain what happens.
Let's say I want to redirect /google to http://google.com. I add the following line to my .htaccess file.
redirect 307 /google http://google.com
I know it's working because I can test with curl from my server. This is hitting apache directly, behind the proxy.
curl -I localhost:8080/google
and I get a 307 as I would expect.
But if this request hits nginx from the outside, nginx knows there is no such file in the web root and responds 404.
Is there a configuration change I can make to remedy this?
Here's my nginx configuration file for this vhost.
server {
listen 80;
root /var/www/mywebsite.com/html;
index index.php index.html index.htm;
server_name mywebsite.com;
access_log /var/log/nginx/mywebsite.com.access.log;
error_log /var/log/nginx/mywebsite.com.error.log;
location / {
try_files $uri $uri/ /index.php;
}
location ~ \.php$ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:8080;
}
location ~ /\. {
deny all;
}
}
It seems that I might need to take the reverse approach and proxy everything but exclude certain file types from the proxy.
Thanks for advice folks!
If you want to forward that request to /google to apache, then just change the location ~ \.php$ pattern to include the request you desire:
location ~ (/google/?)|(\.php)$ {
On the other hand if you want nginx to handle the redirect you can add new rule:
location ~ /google {
return 307 http://google.com;
}
Just make sure to put it before the location block which contains try_files.
EDIT:
To forward all requests that don't hit a file use this:
location /
{
if (!-f $request_filename) #test if a static file does not exists
{
# forward the request if there is no file to serve:
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:8080;
}
}
Additionally if you want for nginx to also serve entire directories then add another condition:
!-d $request_filename
Also note that if you want only specific files to be served then instead location / use the pattern to match those files. For example if you want to serve only jpg's and css's use
location ~ \.(jpg|css)$
EDIT2: Here you have a simplified version of your script, which is also more robust - lets you serve only the types of files you want:
server {
listen 80;
server_name test.lcl;
root /home/www/test;
location / {
try_files $uri $uri/ #apache;
}
location #apache
{
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:8080;
}
}

How to configure nginx rules so that if one failed it serve the request using another

Note, this question is moved to stackoverflow from superuser
I got the following nginx conf:
server {
listen 80;
listen 443 ssl;
...
# specific rule to serve versioned js resources
location ~ ^/js/([0-9\.]+)/(.*)$ {
alias /opt/x/public/deploy/js/$1/$2;
}
location / {
add_header P3P 'CP="CAO PSA OUR"';
proxy_pass http://127.0.0.1:8088;
set $ssl off;
if ($scheme = https) {
set $ssl on;
}
proxy_set_header X-Forwarded-Ssl $ssl;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
}
}
It works as expected. However if a certain versioned js resource does not exists in the deployed dir, say /opt/x/public/deployed/js/1.1/, it will return 404. What I want is in that case nginx shall pass the request to the backend service running at 8088 port instead of returning 404. Is this even doable?
Thanks!
Green
http://wiki.nginx.org/HttpCoreModule#try_files
try_files is your friend, here you can do the order you want to try files and finaly have the proxypass upstream.

Resources