Nginx redirect *:port to subdomain - redirect

I'm working with Nginxand I want to know how can I redirect all request with a specific port to a subdomain ?
This is my default.conf :
server{
listen 80 default_server;
server_name localhost;
location / {
root /usr/share/nginx/html;
}
}
server{
listen 80;
server_name blog.mydomain.com;
location / {
proxy_pass http://my-ip:8080;
}
}
So with this I have the default mydomain.com serve the html folder, and a subdomain blog.mydomain.com serve an application running port 8080.
My problem is when I try to access directly my-ip:8080, or mydomain.com:8080 or blog.mydomain.com:8080 the server serve the application running port 8080 and I want to redirect all these requests to blog.mydomain.com without the :8080.
How can I do that ? Automatically redirect to blog.mydomain.com if I specify :8080 in the url ?

When you use my-ip:8080 or mydomain.com:8080, you call directly your application, not nginx. The issue I see here is not "my webapp doesn't redirect to nginx" but "I have a proxy but my webapp is directly accessible from the internet".
A clean way to fix it is to hide your application from the internet and let nginx be the only way to contact it. Configure your application to listen on localhost (it looks like it listens on * or 0.0.0.0, meaning all interfaces). Then, tell nginx to proxy requests to http://localhost:8080;.
If you really want to keep your application listening on *:8080, you can add a HTTP header in nginx (like X-Forwarded-For with proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;) and detect it in your application. Without it, redirect to nginx. Note that anyone can add HTTP headers...

There is two solutions for your problem:
If you can change code of application then you can handle HTTP request in application. You should be able get information about port from headers.
If you cannot change code of application but you can change port on which application is listening, then you can do redirect in nginx. To do this, you need start listening on port 8080 in nginx and redirect it to 80, and on 80 port you change proxy_pass to new port of application.

Related

HTTP/2 nginx force redirect HTTP to HTTPS breaks expected behaviour

I've setup an example project that uses the latest version of nginx which supports HTTP/2.
I was going off this official blog post: https://www.nginx.com/blog/nginx-1-9-5/
Here is a working code example (with details of how to setup everything within the README - nginx.conf pasted below as well): https://github.com/Integralist/Docker-Examples/tree/master/Nginx-HTTP2
user nobody nogroup;
worker_processes auto;
events {
worker_connections 512;
}
http {
upstream app {
server app:4567;
}
server {
listen *:80 http2;
location /app/ {
return 301 https://$host$request_uri;
}
}
server {
listen *:443 ssl http2;
server_name integralist.com;
ssl_certificate /etc/nginx/certs/server.crt;
ssl_certificate_key /etc/nginx/certs/server.key;
ssl_trusted_certificate /etc/nginx/certs/ca.crt;
location /app/ {
proxy_pass http://app/;
}
}
}
Although the example works, I've hit an issue where by if I go to the service endpoint within my browser using HTTP, it'll first download a file called download and then redirect correctly to HTTPS.
I'm not sure what this file is or why the redirection causes it to happen, but its content is ġˇˇˇˇˇˇ ?
If I try using curl (e.g. curl --insecure http://$dev_ip:$dev_80/app/foo) the redirect fails to happen and I think it's because of this weird downloaded file? The response from curl to stdout is just ??????
I wonder if this is possibly a side-effect of using Docker to containerize the Ruby application and the nginx server?
Update
I removed http2 from listen *:80 http2; so it now reads listen *:80; and the download doesn't happen but the problem I have is trying to get the redirect to point to the correct docker port now :-/
To clarify, I have an nginx container with dynamic port generation (-P). One port for accessing the containerized nginx service on :80 and one for :443 - my nginx.conf is redirecting traffic from HTTP to HTTPS but I need to be able to identify the 443 port number.
e.g. docker ps shows 0.0.0.0:32791->80/tcp, 0.0.0.0:32790->443/tcp
I'm trying to redirect http://example.com:32791/app/foo to https://example.com:32790/app/foo
I'm not sure how I could configure nginx to know the relevant 443 Docker port number as that's dynamically generated?
I could be explicit and use -p when running the nginx container. But I'd still need to pass that port number into nginx as a variable somehow (a quick google would suggest using Docker's -e "my_port=9999" and then access it using nginx's env declaration)
Update 2
I've even tried swapping to explicit ports -p and then hardcoding the port number into the nginx.conf with no luck (e.g. docker run ... -p 60443:443 -p 60080:80)...
listen *:80;
location /app/ {
return 301 https://$host:60443$request_uri;
}
...if I hit http://example.com:60080/app/ it gets redirected to https://example.com:60443/ so almost there but the actual path /app/ wasn't added to the end when redirecting?
the problem I have is trying to get the redirect to point to the correct docker port now
If your nginx docker container is linked (docker run --link) with the ruby one, the correct port is the one EXPOSE(d) in the ruby container image (even if you don't know to which host port that EXPOSE port was mapped)
A direct link container-to-container can use the port mentioned in the dockerfile.

Replace image and javascript absolute paths through proxy_redirect in nginx

I have a scenario as follows.
Nginx is being used as a reverse proxy to a apache server listening at port 8080. nginx is running at port 80. There is a wsgi application which is being run by the apache server.
Now, I have added a proxy_pass to the nginx configuration such that whatever requests come to localhost/ (nginx port is the default port 80) they get redirected to localhost:8080.
Here is an excerpt from the nginx conf file:
server {
listen 80;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
location <app_name> {
proxy_pass http://localhost:8080/
proxy_redirect http://localhost/ http://localhost:8080/
}
}
I have added the proxy redirect to take care of any redirects from the apache server so that any request mapping to http://localhost/<something> gets redirected to http://localhost:8080/<something> because the application's resources are going to be available under port 8080.
Now, the problem here is that the wsgi application generates an html where the image and the javascript location paths are absolute paths like /img/image.png and /js/javascript.js. Now, they are part and parcel of the HTML and do not send any redirect with a complete http:// prefix as such therefore, the server tries to locate the images in the localhost/img directory instead of the localhost:8080/img directory.
A dirty workaround for the same could be to have the /img and /js directories also defined as separate "location" in the server config and a proxy_pass specified to them. But then these directories could be more in number and maintaining the same could potentially become a headache.
Is there a cleaner way of doing this?
This is in reference to fixing the issue in graphite Apache cannot serve graphite-web from URLs other than /
In case where the proxied application (the Graphite app in this case) isn't able to be configured as a "slave" app, it is better to spare a whole subdomain to the application.
Or you may try the ngx_http_sub_module which:
…modifies a response by replacing one specified string by another.
as an example this code will change all the ':/localhost:8080/' to ':/localhost/app_name/':
location <app_name> {
# ...
sub_filter ':/localhost:8080/' ':/localhost/app_name/';
}
Note that:
This module is not built by default, it should be enabled with the --with-http_sub_module configuration parameter.
But in most package systems nginx is built with all it's optional modules already. Just check if you version has the sub_module built in:
nginx -V | grep sub_module
In my case for homebrew it gives output like this.

NGINX - redirect all unconfigured subdomains

I'm happy to join community and want to share with you with my little problem.
I've got wildcard entry for example.com in my DNS which points all subdomains to some machine
* IN A 172.172.172.172
While NGINX configuration for this domain contains only actively used subdomain names
server {
listen 10.0.0.1:80;
server_name example.com www.example.com
moskva.example.com www.moskva.example.com
tokyo.example.com www.tokyo.example.com;
...
}
What I want to achieve is directing all unconfigured subdomains like 'mistake.example.com' to specific address.
Is there any elegant way of solving this problem?
Best Regards
Arek
This will instruct the site to redirect any unmatched traffic to example.com
server {
listen 80 default_server;
return 301 http://example.com;
}
You can set a default server section like this:
server {
listen 10.0.0.1:80 default_server;
server_name _;
...
}

NGinx Domain name redirects

Lets say I have a website named xyz.co, I also have other domain names with the same prefix like xyz.com, xyz.it, xyz.co.it
Right now nginx works fine with server_name xyz.co in nginx.conf in port 80 I would want all the other domains to redirect to xyz.co also I would want www.* versions of the above to redirect to xyz.co. How can I get this? Is this nginx webserver level changes? or I need to make this changes in DNS?
UPDATE: I tried this in nginx.conf but no use...
server
{
listen 80;
server_name xyz.co xyz.com, xyz.it, xyz.co.it;
rewrite ^/(.*) http://xyz.co permanent;
}
I first tried posting this question in ServerFault but no response there - https://serverfault.com/questions/453472/nginx-domain-name-redirects
add one server block for all the domain names that need to be redirected. like this:
server {
listen 80;
server_name xyz.com, xyz.it, xyz.co.it;
rewrite ^ http://xyz.co$request_uri permanent;
}
and another server block for the xyz.co domain:
server {
listen 80;
server_name xyz.co;
#other settings
}
this way when you go to one of the domain names that need to be redirected nginx will simply redirect to xyz.co and move into the other server block where you can add all your settings (rootfolder, location blocks, etc)

nginx + varnish redirect server IP to url

i have nginx on port 8080 sitting behind varnish running on port 80. there is only one website on my server. the problem is you can access it by server's IP address too, instead of just url. google indexed this ip and i am afraid of problems with duplicate content.
how do i redirect requests going to IP address to my URL? i tried this code, but it ended up with loop redirects error.
server {
listen 180.10.1.1:80;
server_name 180.10.1.1;
rewrite .* http://www.mysite.com$request_uri permanent;
}
thanks
edit:
rest of vcl
server {
listen 8080;
server_name site.com;
access_log /var/log/nginx/localhost.access.log;
error_page 502 /502.html;
## Default location
location / {
root /home/site.com/public_html;
index index.php;
...
There's a couple of ways to solve this. If Nginx is also serving site.com when you visit the server IP Address then you should adjust the Nginx config so any requests which are directed at the IP address redirect to site.com. Then restart both Nginx and Varnish.
ok the problem was "180.10.1.1:" in the listen directive. i kept there only "listen 80" and now it works fine :)