nginx reverse proxy for Mikrotik.com - nginx

Hi we need to cache some site like mikrotik in our system but this site is use "HTTPS" protocol and our caching system only cache HTTP protocol site So we thing if we used nginx as reverse proxy so client when visit https://www.mikrotik.com our DNS system well redirect to nginx local ip and nginx well fetch data from mikrotik as HTTP to client our problem is all thing is OK but if client visit any thing inside mikrotik webpage it well redirected to mikrotik original site .. this is sample of nginx config
server
{
listen 80;
server_name mikrotik.com;
location / {
proxy_pass https://mikrotik.com/;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

I guess this is because all the links on the site will still be to https://mikrotik.com/... which you haven't proxied
You could try using the Nginx sub filter module and rewrite all the links within Nginx before you serve them on your network. Adding some directives like this to your location block will get Nginx to rewrite the links from https to http on the fly:
location / {
....
....
sub_filter_types text/html;
sub_filter 'https://mikrotik.com/' 'http://mikrotik.com/';
sub_filter_once off;
sub_filter_last_modified on;
proxy_set_header Accept-Encoding "";
I use this config for a similar purpose but the opposite way around, so going from http to https. Not sure if it will work for you in reverse as the whole point of SSL is to stop you doing this kind of thing, which is basically just a man in the middle attack

Related

How to NGINX reverse proxy to backend server which has a self signed certificate?

I have a small network with a webserver and an OpenVPN Access Server (with own webinterface). I have only 1 public ip and want to be able to point subdomains to websites on the webserver (e.g. website1.domain.com, website2.domain.com) and point the subdomain vpn.domain.com to the web interface of the OpenVPN access server.
After some Google actions i think the way to go is setup a proxy server. NGINX seems to be able to do this with the "proxy_pass" function. I got it working for HTTP backend URL's (websites) but it does not work for the OpenVPN Access Server web interface as it forces to use HTTPS. I'm fine with HTTPS and prefer to use it also for the websites hosted on the webserver. By default a self signed cert. is installed and i want to use also self signed cert. for the other websites.
How can i "accept" self signed cert. for the backend servers? I found that i need to generate a cert. and define it in the NGINX reverse proxy config but i do not understand how this works as for example my OpenVPN server already has an SSL certificate installed. I'm able to visit the OpenVPN web interface via https://direct.ip.address.here/admin but got an "This site cannot deliver an secure connection" page when i try to access the web interface via Chrome.
My NGINX reverse proxy config:
server {
listen 443;
server_name vpn.domain.com;
ssl_verify_client off;
location / {
# app1 reverse proxy follow
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass https://10.128.20.5:443;
proxy_ssl_verify off;
}
access_log /var/log/nginx/access_log.log;
error_log /var/log/nginx/access_log.log;
}
server {
listen 80;
server_name website1.domain.com;
location / {
# app1 reverse proxy follow
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://10.128.11.20:80;
}
access_log /var/log/nginx/access_log.log;
error_log /var/log/nginx/access_log.log;
}
A nearby thought...
Maybe NGINX is not the right tool for this at all (now or on long term)? Lets assume i can fix the cert. issue i currently have and we need more backend web servers to handle the traffic, is it possible to scale the NGINX proxy as well? like a cluster or load balancer or something? Should i look for a completely different tool?

Icecast2 running under nginx not able to connect

I want to start saying that I've looked all over the place to find an answer to this problem and it just seems like either nobody else ran into this problem or nobody is doing it. So, I recently install icecast2 on my Debian server, The thing is that I'm completely able to broadcast to my server from my local network connecting to its local IP on port 8000 and hear the stream over the internet on radio.example.com since I proxy it with nginx, so far no problems at all. The problem lies when I want to broadcast to the domain I gave with nginx stream.example.com
I have two theories, one is that the proxy is not giving the source IP to icecast so it thinks it's beign broadcasted from 127.0.0.1 and the other is that nginx is doing something strange with the data stream and thus not delivering the correct format to icecast.
Any thoughts? Thanks in advance!
Here is the nginx config
server {
listen 80;
listen [::]:80;
server_name radio.example.com;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Real-IP $remote_addr;
location / {
proxy_pass http://127.0.0.1:8000/radio;
subs_filter_types application/xspf+xml audio/x-mpegurl audio/x-vclt text/css text/html text/xml;
subs_filter ':80/' '/' gi;
subs_filter '#localhost' '#stream.example.com' gi;
subs_filter 'localhost' $host gi;
subs_filter 'Mount Point ' $host gi;
}
}
server {
listen 80;
listen [::]:80;
server_name stream.example.com;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Real-IP $remote_addr;
location / {
proxy_pass http://localhost:8000/;
subs_filter_types application/xspf+xml audio/x-mpegurl audio/x-vclt text/css text/html text/xml;
subs_filter ':8000/' ':80/' gi;
subs_filter '#localhost' '#stream.example.com' gi;
subs_filter 'localhost' $host gi;
subs_filter 'Mount Point ' $host gi;
}
}
And this is what I get on icecast error.log
[2018-08-10 14:15:45] INFO source/get_next_buffer End of Stream /radio
[2018-08-10 14:15:45] INFO source/source_shutdown Source from 127.0.0.1 at "/radioitavya" exiting
Not sure how much of this is directly relevant to the OP's question, but here's a few snippets from my config.
These are the basics of my block to serve streams to clients over SSL on port 443.
In the first location block any requests with a URI of anything other than /ogg, /128, /192 or /320 are rewritten to prevent clients accessing any output from the Icecast server other than the streams themselves.
server {
listen 443 ssl http2;
server_name stream.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
rewrite ~*(ogg) https://stream.example.com/ogg last;
rewrite ~*([0-1][0-5]\d) https://stream.example.com/128 last;
rewrite ~*(?|([1][6-9]\d)|([2]\d\d)) https://stream.example.com/192 last;
rewrite ~*([3-9]\d\d) https://stream.example.com/320 break;
return https://stream.example.com/320;
}
location ~ ^/(ogg|128|192|320)$ {
proxy_bind $remote_addr transparent;
set $stream_url http://192.168.100.100:8900/$1;
types { }
default_type audio/mpeg;
proxy_pass_request_headers on;
proxy_set_header Access-Control-Allow-Origin *;
proxy_set_header Host $host;
proxy_set_header Range bytes=0-;
proxy_set_header X-Real-IP $remote_addr;
proxy_buffering off;
tcp_nodelay on;
proxy_pass $stream_url;
}
}
Setting proxy_bind with the transparent flag:
allows outgoing connections to a proxied server originate from a
non-local IP address, for example, from a real IP address of a client
This addresses the issues of local IP addresses in your logs/stats instead of client IPs, for this to work you also need to reconfigure your kernel routing tables to capture the responses sent from the upstream server and route them back to Nginx.
This requires root access and a reasonable understanding of Linux networking configuration, which I appreciate not everyone has. I also appreciate not everyone who uses Icecast and might want to reverse proxy will read this. A much better solution would be making Icecast more Nginx friendly, so I had a go.
I cloned Icecast from github and had a look over the code. I've maybe missed some but these lines looked relevant to me:
./src/logging.c:159: client->con->ip,
./src/admin.c:700: xmlNewTextChild(node, NULL, XMLSTR(mode == OMODE_LEGACY ? "IP" : "ip"), XMLSTR(client->con->ip));
For servers which do not support the PROXY protocol the Nginx default method of passing the client IP upstream is via the X-Real-IP header. Icecast seems to be using the value of client->con->ip for logging listener IPs. Let's change things up a bit. I added this:
const char *realip;
realip = httpp_getvar (client->parser, "x-real-ip");
if (realip == NULL)
realip = client->con->ip;
And changed the previous lines to this:
./src/logging.c:163: realip,
./src/admin.c:700: xmlNewTextChild(node, NULL, XMLSTR(mode == OMODE_LEGACY ? "IP" : "ip"), XMLSTR(realip));
then I built Icecast from source as per the docs. The proxy_set_header X-Real-IP $remote_addr; directive in my Nginx conf is passing the client IP, if you have additional upstream servers also handling the request you will need to add some set_real_ip_from directives specifying each IP, real_ip_recursive on; and use the $proxy_add_x_forwarded_for; which will capture the IP address of each server which handles the request.
Fired up my new Icecast build and this seems to work perfectly. If the X-Real-IP header is set then Icecast logs this as the listener IP and if not then it logs the client request IP so it should work for reverse proxy and normal setups. Seems too simple, maybe I missed something #TBR?
OK so you should now have working listener streams served over SSL with correct stats/logs. You have done the hard bit. Now lets stream something to them!
Since the addition of the stream module to Nginx then handling incoming connections is simple regardless of whether of not they use PUT/SOURCE.
If you specify a server within a stream directive Nginx will simply tunnel the incoming stream to the upstream server without inspecting or modifying the packets. Nginx streams config lesson 101 is all you need:
stream {
server {
listen pub.lic.ip:port;
proxy_pass ice.cast.ip:port;
}
}
I guess one problem unsuspecting people may encounter with SOURCE connections in Nginx is specifying the wrong port in their Nginx config. Don't feel bad, Shoutcast v1 is just weird. Point to remember is:
Instead of the port you specify in the
client encoder it will actually attempt to connect to port+1
So if you were using port 8000 for incoming connections, either set the port to 7999 in client encoders using the Shoutcast v1 protocol, or set up your Nginx stream directives with 2 blocks, one for port 8000 and one for port 8001.
Your Nginx install must be built with the stream module, it's not part of the standard build. Unsure? Run:
nginx -V 2>&1 | grep -qF -- --with-stream && echo ":)" || echo ":("
If you see a smiley face you are good to go. If not you'll need to build Nginx and include it. Many repositories have an nginx-extras package which includes the stream module.
Almost finished, all that we need now is access to the admin pages. I serve these from https://example.com/icecast/ but Icecast generates all the URIs in the admin page links using the root path, not including icecast/ so they won't work. Let's fix that using the Nginx sub filter module to add icecast/ to the links in the returned pages:
location /icecast/ {
sub_filter_types text/xhtml text/xml text/css;
sub_filter 'href="/' 'href="/icecast/';
sub_filter 'url(/' 'url(/icecast/';
sub_filter_once off;
sub_filter_last_modified on;
proxy_set_header Accept-Encoding "";
proxy_pass http://ice.cast.ip:port/;
}
The trailing slash at the end of proxy_pass http://ice.cast.ip:port/; is vitally important for this to work.
If a proxy_pass directive is specified just as server:port then the full original client request URI will be appended and passed to the upstream server. If the proxy_pass has anything URI appended (even just /) then Nginx will replace the part of the client request URI which matches the location block (in this case /icecast/) with the URI appended to the proxy_pass. So by appending a slash a request to https://example.com/icecast/admin/ will be proxied to http://ice.cast.ip:port/admin/
Finally I don't want my admin pages accessible to the world, just my IP and the LAN, so I also include these in the location above:
allow 127.0.0.1;
allow 192.168.1.0/24;
allow my.ip.add.ress;
deny all;
That's it.
sudo nginx -s reload
Have fun.
tl;dr - Don't reverse proxy Icecast.
Icecast for various reasons is better not reverse proxied. It is a purpose built HTTP server and generic HTTP servers tend to have significant issues with the intricacies of continuous HTTP streaming.
This has been repeatedly answered. People like to try anyway and invariably fail in various ways.
If you need it on port 80/443, then run it on those ports directly
If you have already something running on port 80/443, then use another of the remaining 2^64 IPv6 addresses in your /64 and if you are still using legacy IP, get another address, e.g. by spinning up a virtual server in the cloud.
Need HTTPS, Icecast supports TLS (on Debian and Ubuntu make sure to install the official Xiph.org packages as distro packages come without openSSL support)
Make sure to put both private and public key into one file.
This line....
subs_filter '#localhost' '#stream.example.com' gi;
Should probably be....
subs_filter '#localhost' '#example.com' gi;
I am not familiar with nginx so my best guess would be that this line is linking radio.example.com to the main site of example.com. By adding the stream.example.com you are confusing it by directing it to a site that doesn't exist.
I got this from a config file posted here:
Anyway, it wouldn't hurt to try it.

nginx proxied redirects use the port number of the proxy, not the host

I'm setting up a web/app/db stack, and the nginx proxy configuration isn't working the way I thought it would.
so here is an example of the stack...the url of the application is:
https://testapp.com
here is the nginx config:
server {
listen 8886;
server_name _;
root /usr/share/nginx/html;
include /etc/nginx/default.d/*.conf;
#ELB
if ($http_user_agent = 'ELB-HealthChecker/2.0') {
return 200 working;
}
#HTTP to HTTPS
if ($http_x_forwarded_proto != 'https') {
return 301 https://$host$request_uri;
}
location / {
set $proxy_upstream_name "testapp.com";
port_in_redirect off;
proxy_pass http://internal-alb.amazonaws.com:8083/;
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-Host $server_name;
proxy_set_header Access-Control-Allow-Origin $http_origin;}
The app is proxied to an internal AWS alb, and it forwards it to a single (at this point) application server.
I'm able to get the site to serve. However, the application creates a redirect on login, and I get the following response.
Request URL:https://testapp.com/login
Request Method:POST
Status Code:302
Remote Address:34.192.444.29:443
Referrer Policy:no-referrer-when-downgrade
Response Headers
content-language:en-US
content-length:0
date:Mon, 11 Sep 2017 18:35:34 GMT
location:http://testapp.com:8083/testCode
server:openresty/1.11.2.5
status:302
The redirect fails because it's being served on 443, not 8083.
For some reason the app or the proxy isn't updating the port as it doing it's reverse proxy thing, so that the redirect has the proxied port NOT the actual application port 443.
What do I need to do with nginx config to get it to redirect correctly.
thanks.
myles.
The normal behaviour of the nginx is to rewrite the upstream address to the address the page was served from. It looks like instead of using your upstream address (http://internal-alb.amazonaws.com:8083/), your app is responding using a mixture of the two (http://testapp.com:8083). You can either change the app behaviour, or, to fix it at the nginx level, can use the proxy_redirect directive.
I'm reasonably sure the directive to fix this is proxy_redirect http://testapp.com:8083/ https://testapp.com/;

Artifactory Browsing With Nginx & HTTP SSO Too Slow

I have setup a reverse proxy between Nginx and Artifactory, following instructions from here : https://www.jfrog.com/confluence/display/RTF/nginx
I've also enabled HTTP SSO in Artifactory so that a user authenticated by Artifactory is able to log in to Artifactory automatically. Instructions followed from here : https://www.jfrog.com/confluence/display/RTF/Single+Sign-on
Everything is working except that Artifactory is really slow. When I go to the website (eg. artifactory.myorg.com/webapp/#/home,) a progress wheel comes up and it keeps rolling and on every page.
If I turn off Nginx and access Artifactory using its embedded Tomcat engine then everything works fine.
Is there anything I can do to fix this ?
Update
The browsing is fine as soon as I turn off the following setting:
proxy_set_header REMOTE_USER $remote_user;
I am guessing that Artifactory is currently processing this user setting for every request and maybe I need to do something at Tomcat side or to Artifactory settings to resolve that.
Here's how my nginx/artifactory config looks (They were generated by Reverse Proxy setup page in Artifactory 4.4):
ssl_certificate /etc/ssl/certs/dummy.crt;
ssl_certificate_key /etc/ssl/keys/dummy.key;
ssl_session_cache shared:SSL:1m;
ssl_prefer_server_ciphers on;
server {
listen 443 ssl;
server_name dummy.net;
if ($http_x_forwarded_proto = '') {
set $http_x_forwarded_proto $scheme;
}
## Application specific logs
access_log /var/log/nginx/dummy-access.log;
error_log /var/log/nginx/dummy-error.log;
rewrite ^/$ /artifactory/webapp/ redirect;
rewrite ^/artifactory$ /artifactory/webapp/ redirect;
location /artifactory/ {
auth_pam "Secure Zone";
auth_pam_service_name "sevice";
proxy_read_timeout 900;
proxy_pass_header Server;
proxy_cookie_path ~*^/.* /;
proxy_pass http://127.0.0.1:8081/artifactory/;
proxy_set_header DUMMY_USER $remote_user;
proxy_set_header X-Artifactory-Override-Base-Url $http_x_forwarded_proto://$host:$server_port/artifactory;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
Yes. Using Nginx as a reverse proxy should not add noticeable overhead, and could speed up the experience if you use it to serve the static assets.
Your testing so far as implicated Nginx, so posting your related Nginx configuration would be helpful.
But I'll go out a limb and make a guess without seeing it. You are likely using proxy_pass in Nginx to send requests on to Artifactory. If Artifactory is on the same host as Nginx, the proxy_pass address should be a port on 127.0.0.1. If you are instead including a domain name there, then your traffic might doing some like being routed from Nginx back to a load balancer, through CloudFlare, or some other inefficient route.
After trying to reproduce your scenario a few times would recommend to try one more thing to isolate the problem.
Try to set a fix username in the REMOTE_USER value, instead of a variable.
proxy_set_header REMOTE_USER username;
BTW, from the snippet it appears the header name is DUMMY_USER and in the example you specified REMOTE_USER. Make sure you the header name is the same as configured in Artifactory under the Admin > Security | HTTP-SSO .
If this issue still reproduces, please contact support#jfrog.com.

Open remote Meteor DDP Connection behind reverse proxy

I am struggling to open a connection from https://siteA.com to https://siteB.com using Meteor's DDP.connect() where both servers reside behind nginx reverse proxies forwarding from http to https.
Things work fine in development. In production, when I run DDP.connect('siteB.com') in the console of siteA, I receive:
Mixed Content: The page at 'https://siteA.com/' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://siteB.com/sockjs/info?cb=zw6j36l90y'. This request has been blocked; the content must be served over HTTPS.
In my current nginx configuration for siteB, I have the following (in relevant part, lmk if more is required):
server {
listen 80 default_server;
location / {
rewrite ^ https://$server_name$request_uri? permanent;
}
}
server {
listen 443 ssl spdy;
add_header Access-Control-Allow-Origin 'https://siteA.com';
proxy_pass http://localhost:3000;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Nginx-Proxy true;
proxy_redirect off;
}
I get that it's complaining that the request terminates in an http endpoint (http://localhost:3000) but I'm not sure what to do about it.
If I change siteB's nginx config to proxy_pass https://localhost:3000 it results in a 502 Bad Gateway.
I have tried things both with and without Meteor's force-ssl package on siteB.
Neither site includes Meteor's browser-policy package - based on my reading the default setting without the package should allow me to connect anywhere as is.
I also tried DDP.connect("ws://siteB.com"); but this resulted in:
XMLHttpRequest cannot load ws://siteB.com/sockjs/info?cb=9lahswe7_9. Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https, chrome-extension-resource.
Should I be listening on a different port? Is there an nginx config setting to whitelist this request? Any help is appreciated.
After some initial googling here a small hint: Mixed Content: The page at 'XYZ' was loaded over HTTPS, but requested an insecure over https
...even though it talks about stylesheets not XMLHttpRequest it is definately related

Resources