Nginx proxy pass based on url part to port - nginx

Is it possible to set up nginx to reverse proxy server.com/[port]/rest/of/url to server.com:[port]/rest/of/url ?
For example,
server.com/12345/files should proxy server.com:12345/files. The ports are random and there could 100s of such ports.
I have docker containers in a linux VM which bind to random ports on the host and serve HTTP. I'm trying to setup a proxy for them on a single port.

Something like this should do the trick:
server {
listen 80;
location ~ ^/(?<port>\d+)/ {
rewrite ^/\d+(/.*) $1 break;
proxy_pass http://127.0.0.1:$port;
}
}
See the following links for more details:
http://nginx.org/r/location
http://nginx.org/r/rewrite
http://nginx.org/r/proxy_pass

Related

How to let the backend api handle https certificate?

I'm new to nginx.
I have a machine, behind my router, that runs a server and handles correctly 80 and 443 request with Https.
Problem is that I want to host a second website on another device but I have only one IP address. I bought a raspberry pi zero to use it as a reverse proxy behind my router. I install nginx and want to redirect all the request to my other machines. Both the RPI 0 and the old machine have local IP.
To redirect requests from my router to RPI 0 and then to my old machine, I used proxy_pass. On port 80 everything works fine, but on port 443 I get a certificate error on my browser.
Is it possible to let the whole request go on the old machine and let the old machine handles the https certificate like before ? Or is it mandatory to have the certificate processed by nginx ?
Diagram of the old but functional installation
Current installation with certificate error
My configuration:
upstream backend_a {
server 192.168.0.20:80;
}
upstream backend_a_s {
server 192.168.0.20:443;
}
server {
listen 80;
server_name mydomain;
location / {
include proxy_params;
proxy_pass http://backend_a;
}
}
server {
listen 443 ssl;
server_name mydomain;
location / {
include proxy_params;
proxy_pass https://backend_a_s;
}
}
I found a solution. I need to use port forwarding. To do this in nginx, I need to use stream keyword.
stream {
server {
listen 443;
proxy_pass 192.168.0.20:443;
}
}
The stream keyword need to be at the same level as http, so I needed to edit /etc/nginx/nginx.conf source. Other solution is to manually compile a version of nginx, with the parameter --with-stream source.

How can I keep port and url without updating Gitlab nginx?

nginx(ng1): 172.168.240.5
Gitlab includ nginx (ng2): 172.168.240.55
ng1 config
listen 81;
server_name ng1;
location /gitlab/ {
proxy_pass 172.168.240.55/
}
how can I keep port and url without updating ng2. // only modify ng1
url gitlab lost
it's login(POST) http://ng1:81/gitlab/users/sign_in
but it's show http://ng1:81/users/sign_in instead of http://ng1:81/gitlab/users/sign_in
it seems to be rewrite by ng2
url gitlab and port lost
click one file in http://ng1:81/gitlab/root/pg/
but it's http://ng1/root/pg/index.html instead of http://ng1:81/gitlab/root/pg/index.html
need nginx reverse proxy
/servername/port/ for dynamic servername and port
I find resolve (dns server + nginx)
Using nginx regex location matching to dynamically map URI's to different ports for multiple reverse proxies

How do I preserve the requested port when using proxy pass?

In the long run what I'm trying to do is to be able to connect to any domain through any port, for example, mysite.com:8000 and then through Nginx have it get routed to an internal ip through the same port. So for example to 192.168.1.114:8000.
I looked into iptables although I'm planning on having multiple domains so that really doesn't work for me in this case (feel free to correct me if I'm wrong). I made sure that the internal ip and port that I'm trying to access is connectable and running and also that the ports I'm testing with are accessible from outside my network.
Here's my Nginx config that I'm currently using:
server {
set $server "192.168.1.114";
set $port $server_port;
listen 80;
listen 443;
listen 9000;
server_name mysite.com;
location / {
proxy_pass http://$server:$port;
proxy_set_header Host $host:$server_port;
}
}
Currently what happens is that when I send a request it just times out. I've been testing using port 80 and also port 9000. Any ideas on what I might be doing wrong? Thanks!
EDIT:
I changed my config file to look like the following
server {
listen 9000;
server_name _;
location / {
add_header Content-Type text/html;
return 200 'test';
}
I keep getting the same exact error. The firewall is turned off so it just seems like Nginx isn't listening on port 9000. Any ideas on why that might be the case?
The most effective way would be to have three separate server directives, one for each port. That way, the upstream server isn't dynamic, so Nginx knows it can keep long-lived connections open to each one.
If you really don't want to do this, you might be able to get around it by doing something like this:
proxy_pass http://upstream_server.example:$server_port;
$port doesn't exist, but $server_port does, so that should work. (It's not $port because there are two ports for each connection: the server port and the client port, which are $server_port and $remote_port, respectively.)

Nginx Reverse Proxy upstream not working

I'm having trouble figuring out load balancing on Nginx. I'm using:
- Ubuntu 16.04 and
- Nginx 1.10.0.
In short, when I pass my ip address directly into "proxy_pass", the proxy works:
server {
location / {
proxy_pass http://01.02.03.04;
}
}
When I visit my proxy computer, I can see the content from the proxy ip...
but when I use an upstream directive, it doesn't:
upstream backend {
server 01.02.03.04;
}
server {
location / {
proxy_pass http://backend;
}
}
When I visit my proxy computer, I am greeted with the default Nginx server page and not the content from the upstream ip address.
Any further assistance would be appreciated. I've done a ton of research but can't figure out why "upstream" is not working. I don't get any errors. It just doesn't proxy.
Okay, looks like I found the answer...
two things about the backend servers, at least for the above scenario when using IP addressses:
a port must be specified
the port cannot be :80 (according to #karliwsn the port can be 80 it's just that the upstream servers cannot listen to the same port as the reverse proxy. I haven't tested it yet but it's good to note).
backend server block(s) should be configured as following:
server {
# for your reverse_proxy, *do not* listen to port 80
listen 8080;
listen [::]:8080;
server_name 01.02.03.04;
# your other statements below
...
}
and your reverse proxy server block should be configured like below:
upstream backend {
server 01.02.03.04:8080;
}
server {
location / {
proxy_pass http://backend;
}
}
It looks as if a backend server is listening to :80, the reverse proxy server doesn't render it's content. I guess that makes sense, since the server is in fact using default port 80 for the general public.
Thanks #karliwson for nudging me to reconsider the port.
The following example works:
Only thing to mention is that, if the server IP is used as the "server_name", then the IP should be used to access the site, means in the browser you need to type the URL as http://yyy.yyy.yyy.yyy or (http://yyy.yyy.yyy.yyy:80), if you use the domain name as the "server_name", then access the proxy server using the domain name (e.g. http://www.yourdomain.com)
upstream backend {
server xxx.xxx.xxx.xxx:8080;
}
server {
listen 80;
server_name yyy.yyy.yyy.yyy;
location / {
proxy_pass http://backend;
}
}

Dynamically listen on an nginx port

I'd like to pass a port to Nginx to listen on dynamically. So I can write something like:
PORT=4567 nginx -c $PWD/nginx.conf
and then have an nginx config that looks something like:
http {
server {
listen $PORT;
}
}
and have nginx listen on the specified port. I tried compiling nginx with lua support, and writing:
events {
worker_connections 200;
}
env SERVER_PORT;
http {
server {
set_by_lua_block $sp {
return os.getenv("SERVER_PORT");
}
listen $sp;
root /Users/kevin/code/nginx-testing;
}
}
But this doesn't work, either; $sp doesn't get defined until the rewrite phase.
Are there any options here or am I resigned to rewriting the config file via sed or similar before starting nginx?
Kevin
The listen directive does not support nginx variable or ENV variable.
So it cannot listen on a nginx port dynamically.
Dynamical listen via ENV variable is technically feasible, you should modify nginx core.
But it cannot be implemented via nginx variable, nginx must listen on some specified port before receiving http requests.
(nginx variable system works on http request.)
You can write some script to modify "listen" directive before starting nginx, which is a not-so-good way to implement dynamic listen.

Resources