Nginx Ingress Selective Reverse Proxy Location Rewrite - nginx

I have an Nginx Ingress that I'm trying to use to replace my HTTPD reverse proxy.
One of my servers behind the proxy returns a redirect containing this url https://proxy/endpoint. Originally with my HTTPD reverse proxy, I was able to modify outgoing http/https traffic headers (specifically location) and regex the proxy to the proper external dns name. How can I achieve this with Nginx Ingress. I see
nginx.ingress.kubernetes.io/proxy-redirect-from
nginx.ingress.kubernetes.io/proxy-redirect-to
Essentially I would like to modify the outgoing traffic to change the location from https://proxy to whatever I need it to be.

It was indeed those two fields I had to add as annotations to my Ingress.yaml. Once those were in place, things got routed correctly.

Related

Reverse proxy with http inbound, https outbound, and parent proxy

I have an application that needs to use a proxy (call it proxy1) to access some https endpoints outside of its network. The application doesn't support proxy settings, so I'd like to provide it a reverse proxy url, and I would prefer not to provide tls certs for proxy1, so I would use http for application -> proxy1.
I don't have access to the application host or forward proxy mentioned below, so I cannot configure networking there.
The endpoints the application needs are https, so proxy1 must make its outbound connections via https.
Finally, this whole setup is within a corporate network that requires a forward proxy (call it proxy2) for outbound internet, so my proxy1 needs to chain to proxy2 / use it as a parent.
I tried squid and it worked well for http only, but I couldn't get it to accept http inbound while using https outbound. Squid easily supported the parent proxy2.
I tried haproxy, but had the same result as with squid.
I tried nginx and it did what I wanted with http -> proxy -> https, but doesn't support a parent proxy. I considered setting up socat as in this answer, or using proxy_pass and proxy_set_header as in this answer, but I can't shake the feeling there's a cleaner way to achieve the requirements.
This doesn't seem like an outlandish setup, is it? Or is there a preferred approach for it? Ideally one using squid or nginx.
You can achive this without the complexity by using a port forwarder like socat. Just install it on a host to do the forwarding (or locally on the app server if you wish to) and create a listener that forwards connections through the proxy server. Then on your application host use a local name resolution overide to map the FQDN to the forwarder.
So, the final config should be the app server using a URI that points to the forwarding server (using its address if no name resolution excists), which has a socat listener that points to the the corporate proxy. No reverse proxy required.
socat TCP4-LISTEN:443,reuseaddr,fork \
PROXY:{proxy_address}:{endpoint_fqdn}:443,proxyport={proxy_port}
Just update with your parameters.

How can I get the real IP of a client when using an ELB in front of my Nginx Ingress?

I have the following setup:
Client -> AWS ELB -> Nginx Ingress -> Pod
In the ELB logs, I can see the real IP of these clients. ELB sends it as the X-Forwarded-For header value to my Ingress controller.
I need to set the whitelist-source-range in the Ingress for the application, but the issue is that it uses the remote IP address, not the one in the X-Forwarded-For header.
I can see some solutions here:
Transform ALB into an NLB, so it preserves the originating client's IP
Make the Nginx controller source range whitelist based on the X-Forwarded-For header
Make the Nginx controller transform the request originating IP into the one in the header
The first is not ideal for me. I didn't want to maintain and pay for another load balancer. I don't know if the second is possible. I think the third is feasible, yet I have no idea how to do it. I know there's something related, which is the proxy protocol, but I don't see how it works, and I don't want to add something I don't understand into my production environment.
The load balancer is for several applications in my Kubernetes environment, so adding these IPs to the whitelist in the security group is not ideal.
How could I solve this issue?
My last resource will be to use Cloudflare. I want to keep as much of my configuration as possible inside Kubernetes, but I'll go for it if it's impossible.
Edit: this doesn't solve my problems, I have CIDRs to whitelist, not a specific IP.
So if you are on AWS, why are you using an Nginx Ingress controller?
You can use the AWS Load Balancer Controller, which will provision and/or manage AWS ALB's automatically.
For your particular usecase, you could add a WAF WebACL for a particular target in the ALB. You can do that manually, or use the alb.ingress.kubernetes.io/wafv2-acl-arn annotation for the AWS Load Balancer Controller.
Alternatively, you could run a separate ALB in a separate subnet, and setup IP whitelisting via the security group of that ALB's. And then make sure that separate ALB is only used for those ingresses that need it.
Again, when using the AWS Load Balancer Controller instead of the Nginx Ingress Controller, this can be done automatically, without extra maintenance.

putting Nginx in front of Logstash?

When I search for nginx logstash , most talks about hadling nginx log with logstash.
I'm not doing that.
I'm thinking of putting Nginx in front of logstash.
Is it ok or beneficial to let logstash handle the http requests directly? (Because I couldn't find docs which puts Nginx in front of logstash, I think the term for this pattern is reverse proxy.. although I don't get why it's called reverse nor proxy)

How to use NGINX as forward proxy for any requested location?

I am trying to configure NGINX as a forward proxy to replace Fiddler which we are using as a forward proxy. The feature of Fiddler that we use allows us to proxy ALL incoming request to a 8888 port. How do I do that with NGINX?
In all examples of NGINX as a reverse proxy I see proxy_pass always defined to a specific upstream/proxied server. How can I configure it so it goes to the requested server, regardless of the server in the same way I am using Fiddler as a forward proxy.
Example:
In my code:
WebProxy proxyObject = new WebProxy("http://mynginxproxyserver:8888/",true);
WebRequest req = WebRequest.Create("http://www.contoso.com");
req.Proxy = proxyObject;
In mynginxproxyserver/nginx.conf I do not want to delegate the proxying to another server (e.g. proxy_pass set to http://someotherproxyserver). Instead I want it to just be a proxy server, and redirect requests from my client (see above) to the request host. That's what Fiddler does when you enable it as a proxy: http://docs.telerik.com/fiddler/Configure-Fiddler/Tasks/UseFiddlerAsReverseProxy
Your code appears to be using a forward proxy (often just "proxy"), not reverse proxy and they operate quite differently. Reverse proxy is for server end and something client doesn't really see or think about. It's to retrieve content from the backend servers and hand to the client. Forward proxy is something the client sets up in order to connect to rest of the internet. In turn, the server may potentially know nothing about your forward proxy.
Nginx is originally designed to be a reverse proxy, and not a forward proxy. But it can still be used as a forward one. That's why you probably couldn't find much configuration for it.
This is more a theory answer as I've never done this myself, but a configuration like following should work.
server {
listen 8888;
location / {
resolver 8.8.8.8; # may or may not be necessary.
proxy_pass http://$http_host$uri$is_args$args;
}
}
This is just the important bits, you'll need to configure the rest.
The idea is that the proxy_pass will pass to a variable host rather than a predefined one. So if you request http://example.com/foo?bar, your http header will include host of example.com. This will make your proxy_pass retrieve data from http://example.com/foo?bar.
The document that you linked is using it as a reverse proxy. It would be equivalent to
proxy_pass http://localhost:80;
You can run into url encoding problems when using the $uri variable as suggested by Grumpy, since it is decoded automatically by nginx. I'd suggest you modify the proxy pass line to
proxy_pass http://$http_host$request_uri;
The variable $request_uri leaves the encoding in tact and also contains all query parameters.

how to print dynamic port in nginx reverse proxy

I want to print the dynamic port created by Nginx in reverse proxy mode, so as to capture the specific packet.
I have go through the nginx docs, but not find something useful. by the way, any other alternatives are welcome

Resources