proxy_pass http://myserver;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
Above is my nginx configuration, and myserver requires NTLM authentication.
I access myserver through nginx proxy and provide correct auth info,but the browser prompt auth again.
Any wrong with my configuration?
EIDT:
Referred to this ,I use stream proxy and problem solved!
Thanks to #Tarun Lalwani
According to nginx documentation:
Allows proxying requests with NTLM Authentication. The upstream connection is bound to the client connection once the client sends a request with the “Authorization” header field value starting with “Negotiate” or “NTLM”. Further client requests will be proxied through the same upstream connection, keeping the authentication context.
upstream http_backend {
server 127.0.0.1:8080;
ntlm;
}
The "ntlm" option is available only for Nginx Plus.
I created a custom module that is able to provide a similar functionality
gabihodoroaga/nginx-ntlm-module
There is also a blog post about this at hodo.dev
Related
Due to a mess of work networks i need to setup an NGINX reverse proxy to an external website that goes via the company MPLS proxy.
This is so other apps can point to an internal DNS address via HTTPS and then that address can either point to an internal STUB App which does not go through a proxy, or it's pointed to and ALB Listening on HTTPS that is pointed to the Reverse Proxy EC2 running listening on HTTP which sends it out to the External Host as a NGINX Transparent Reverse Proxy via HTTPS.
On the EC2 Instance if i do curl -x http://111.222.333.444:1234 https://external.host.name:5678 i get back an expected result from hitting the external host but i cannot get the same responce back from my nginx x host the upstream proxy seems to be denied access "Access Denied (policy_denied)"
Since i am not on my work computer i have to manually type out my current configuration so sorry if i make a mistake (Ip Addresses and Hosts obscured for obvious security reasons)
Also to rule out SELINUX issues i've set setenforce 0 for the moment untill i can get a working connection.
There are HTTP_PROXY and HTTPS_PROXY variables on the box set to another broxy, but i don't believe NGINX is using them, though i could be wrong.
My current configs after several hours of playing around:
under /etc/nginx/conf.d/proxy.conf
upstream proxy {
server 111.222.333.444:1234
}
under /etc/nginx/default.d/reverse-proxy.conf
location / {
proxy_buffering off;
proxy_pass http://proxy;
proxy_redirect http://proxy https://external.host.name:5678;
proxy_set_header Host external.host.name;
proxy_set_header Referer $http_referer;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-For $scheme;
proxy_set_header X-Forwarded-Host $host:$server_port;
proxy_set_header X-Forwarded-Server $host;
}
I believe that's the whole config at current, Sorry if i've forgotten anything. Does anyone have a working config for this type of setup or show me where i'm going wrong please?
Edit:
Further Info, if i do curl http://111.222.333.444:1234/https://external.host.name:5678 I get the same error as the NGINX result
The only difference i can see is the Host Header
on the failed one the Header is "Host: 111.222.333.444:1234"
on the success the Header is "Host: external.host.name:5678" and there's an additional header "X-Forwarded-For: 555.666.777.888"
I have not been able to figure out what the ip in the X-Forwarded-For is as it's not the box i am on
I have tried the following but all i get back from the proxy is Network Error (dns_server_failure)
location / {
proxy_buffering off;
proxy_pass http://111.222.333.444:1234/https://external.host.name:5678;
proxy_set_header Host external.host.name:5678;
proxy_set_header X-Forwarded-For 555.666.777.888;
}
I'm using Jenkins with ec2 and Elastic Balancer(ELB). Everything works fine until I add https protocol to ELB.
The architecture shown as below:
client (https) <-> ELB (Http) <-> Nginx (Http) <-> Jenkins
Protocol https only happens between client and ELB. When first visit Jenkins home page, visitor is redirected to the login page. Here comes the problem, as you can see, for Jenkins itself, it only can see the http request. However, the real address should start with https.
After debugging, it turns out that spring security component return the 302 response http://jenkins/login instead of https://jenkins/login. For further information, I found out that spring security component gets proto from servlet server, who only can see the http request.
I don't think this make sense or there are some problems, because in the nginx configuration file, I wrote this
proxy_set_header Upgrade $http_upgrade;
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;
I've tried to change the 302 Location header to https://jenkins/login, obviously, this is not the solution.
How can I solve this problem?
My app runs on Google Compute Engine. Nginx used as a proxy server. Nginx was configured to use SSL. Below is the content of /etc/nginx/sites-available/default:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name mywebapp.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
include snippets/ssl-mywebapp.com.conf;
include snippets/ssl-params.conf;
root /home/me/MyWebApp/wwwroot;
location /.well-known/ {
}
location / {
proxy_pass http://localhost:5000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
In Startup.cs I have:
app.UseGoogleAuthentication(new GoogleOptions()
{
ClientId = Configuration["Authentication:Google:ClientId"],
ClientSecret = Configuration["Authentication:Google:ClientSecret"],
});
Now in Google Cloud Platform I need to specify Authorized redirect URIs. If I enter the following, my web app works as expected:
http://mywebapp.com/signin-google
But, it won't work if https is used; browser displays the following error:
The redirect URI in the request, http://mywebapp.com/signin-google, does
not match the ones authorized for the OAuth client.
In this case, is it safe to use http as authorized redirect uri? What configuration do I need if I want it to be https?
This happens because your application which is running behind a reverse proxy server doesn't have any idea that originally request came over HTTPS.
SSL/TLS Termination Proxy
The configuration of the reverse proxy described in the question is called SSL/TLS Termination reverse proxy. That means that secure traffic is established between a client and a proxy server. The proxy server decrypts a request and then forwards it to an application over HTTP protocol.
The issue with this configuration is that an application behind it is not aware that client sent request over HTTPS. So when it comes to redirect to itself it uses HttpContext.Request.Scheme, HttpContext.Request.Host and HttpContext.Request.Port to build a valid URL for redirect.
X-Forwarded-* HTTP Headers
This is where X-Forwarded-* headers come into play. To let the application know that request is originally coming through a proxy server over HTTPS we have to configure the proxy server to set X-Forwarded-For and X-Forwarded-Proto HTTP headers.
location / {
proxy_pass http://localhost:5000;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
OK, now if we get back to ASP.NET Core application and take a look at incoming HTTP request we will see both X-Forwarded-* headers set, however a redirect URL still uses HTTP scheme.
Forwarded Headers Middleware
Basically this middleware overrides HttpContext.Request.Scheme and HttpContext.Connection.RemoteIpAddress to values which were provided by X-Forwarded-Proto and X-Forwarded-For headers appropriately. To make it happen let's add it to pipeline by adding the following line somewhere in the beginning of the Startup.Configure() method.
var forwardedHeadersOptions = new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto,
RequireHeaderSymmetry = false
};
forwardedHeadersOptions.KnownNetworks.Clear();
forwardedHeadersOptions.KnownProxies.Clear();
app.UseForwardedHeaders(forwardedHeadersOptions);
This should eventually make your application construct valid URLs with HTTPS scheme.
My Story
The code above looks different to what Microsoft suggests. If we take a look in documentation their code looks a bit shorter:
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});
However this didn't work for me. Also according to the comments under this issue I'm not alone.
I have a nginx set up as reverse proxy for ASP.NET Core application running in Docker container. It became more complicated after I put everything behind Amazon Load Balancer (ELB).
I followed advice from the documentation first, but it didn't work for me. I have got the following warning in my app:
Parameter count mismatch between X-Forwarded-For and X-Forwarded-Proto
Then I looked at my X-Forwarded-* headers and realized that they had different length. X-Forwarded-For header was containing 2 records (comma separated IP addresses), while X-Forwarded-Proto only one record https. This is how I came up to setting the property RequireHeaderSymmetry to false.
Well, I got rid of 'Parameter count...' warning message, but immediately after that I faced another odd debug message:
Unknown proxy: 172.17.0.6:44624
After looking into the source code of ForwardedHeadersMiddleware I have finally figured out that I have to either clean up both KnownNetworks and KnownProxies collections of the ForwardedHeadersOptions or add my docker network 172.17.0.1/16 to the list of known networks. Right after that I have finally got it working.
PS: For those who sets up a SSL/TLS termination on load balancer (e.g. Amazon Load Balancer or ELB) DON'T set header X-Forwarded-Proto in nginx configuration. This will override correct https value which came from load balance to the http scheme and redirect url will be wrong. I have not found yet how to just append scheme used in nginx to the header instead of overriding it.
For apache users, need to add only one header:
RequestHeader set X-Forwarded-Proto "https"
Firstly need to be sure that mod_headers is enabled.
How do I use nginx as proxy for a websocket ?
If I need to connect to socketSite.com:port from clientSite.com( javascript)
And I won't to show user's link "socketSite.com:port "
Can I use nginx proxy for redirecting requests from/to websocket server ?
Absolutely, you can! Use the following configuration:
location /myHandler{
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header HOST $host;
proxy_set_header X_Forwarded_For $remote_addr;
proxy_pass http://localhost:8880;
proxy_redirect default;
client_max_body_size 1000m;
}
I use spring websocket. /myHandler is my URL to create the websocket connection, http://localhost:8880; is my Tomcat server address. Nginx server and Tomcat are running on the same machine.
I've installed GitLab 8.0.2 on a VM, and I have an nginx reverse proxy set up to direct HTTP traffic to the VM. I am able to view the main login page for GitLab, but when I try to login using the Google OAuth2 method, the callback fails to log me in after entering my correct credentials. I simply get directed back to the GitLab login page.
Where might the problem be? The reverse proxy settings? GitLab settings (ie. Google OAuth config)?
Below is my nginx conf:
upstream gitlab {
server 192.168.122.134:80;
}
server {
listen 80;
server_name myserver.com;
access_log /var/log/nginx/gitlab.access.log;
error_log /var/log/nginx/gitlab.error.log;
root /dev/null;
## send request back to gitlab ##
location / {
proxy_pass http://gitlab;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_redirect off;
proxy_buffering off;
proxy_set_header Host $http_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;
}
}
Interestingly, the old setup I had used iptables to redirect port 81 on the host machine to port 80 on the GitLab VM, and, in that case, the Google OAuth callback worked. I'd prefer to have people simply use standard port 80 for accessing my GitLab instance, though, so I want this reverse proxy method to work.
GitLab 8.x has quite a few new things. Although I don't see anything specifically wrong with your nginx.conf file, it is pretty short compared to the example in the GitLab repository. Look through https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/support/nginx/gitlab-ssl to get an idea of the configuration you should consider adding.
Once your nginx.conf file is updated, read through GitLab OmniAuth documentation and the Google OAuth2 integration documentation under 'Providers' on that OmniAuth page. Make sure you provide the correct callback URL to Google when registering.