Enabling proxy protocol in Nginx for just one vhost without breaking the others? - nginx

I just set up HAProxy on a server by itself to act as a reverse proxy. This will send the traffic to a main server that's running Nginx.
I got it almost working, aside from being able to pass the original IP through from the proxy server to the web server.
I'm using mode tcp in haproxy since a lot of the traffic coming in will already be on port 443 using SSL. I read that I can't use the option forwardfor in tcp mode, and I can't send SSL traffic using mode http. So I added send-proxy to the server lines, and then tried to enable the proxy protocol on Nginx.
That actually worked for the domain I'm running, but we have about 10 other virtualhost domains being hosted on that same machine, and as soon as I enabled proxy protocol on one vhost separately, it broke ALL of our other domains pointing to that server, as they all started timing out.
Is there a way around this? Can I enable proxy protocol for just one virtualhost on Nginx without breaking the rest of them? Or is there a way to just use http mode with the forwardfor option, even if it's sending SSL traffic?
Below is my haproxy config, with the IPs redacted:
global
maxconn 10000
user haproxy
group haproxy
defaults
retries 3
timeout client 30s
timeout server 30s
timeout connect 30s
mode tcp
frontend incoming
bind *:80
bind *:443
option tcplog
default_backend client_proxy
backend client_proxy
use-server ps_proxy_http if { dst_port 80 }
use-server ps_proxy_https if { dst_port 443 }
server ps_proxy_http XXX.XXX.XXX.XXX:80 send-proxy
server ps_proxy_https XXX.XXX.XXX.XXX:443 send-proxy
This is my first time using HAProxy as a reverse proxy, so any insight would be much appreciated.

Related

Using HAProxy to Front Amazon S3

I have Direct Connect over a fast pipe to an AWS VPC and I'd like to use a cluster of HAProxy instances in my VPC to reverse-proxy one or more S3 buckets. This is so my users on premises can enjoy the increased bandwidth.
I guess the main question is whether this is doable, with the follow-on, "Is there a better solution for this than HAProxy?" I don't want to use an explicit proxy like squid because my only use-case for this is S3.
Assuming HAProxy is fine, I did a quick dummy setup for one bucket as a POC. When I connect directly to the bucket without credentials (simply to test connectivity), I see the "Access Denied" XML response I expect. But when I connect to the reverse-proxy, it seems to redirect me to https://aws.amazon.com/s3/. How am I screwing this up?
Here's my config (replace MY_BUCKET with any bucket name):
global
daemon
maxconn 256
defaults
mode http
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
frontend http-in
bind *:80
default_backend servers
backend servers
server server1 MY_BUCKET.s3.amazonaws.com:80 maxconn 100
UPDATE:
Per Pedro's request, here is the configuration I found that makes this work. As you can see, it's extremely bare bones. (I'm using an EC2 instance with two CPUs.)
global
daemon
nbproc 2
nbthread 1
defaults
mode tcp
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
frontend http-in
bind *:80
default_backend S3
backend S3
server server1 s3.amazonaws.com:80
Proxying from HAProxy to Amazon S3 is definitely possible! Below is a copy of our production config file. We are using HAProxy 2.2 but this should be backward compatible to older versions as well.
resolvers dns
parse-resolv-conf
hold valid 10s
frontend wwoof
mode http
bind *:80
default_backend s3
backend s3
mode http
http-request set-header Host your-bucket.s3-website.eu-west-3.amazonaws.com
http-request del-header Authorization
http-response del-header x-amz-id-2
http-response del-header x-amz-request-id
server s3 your-bucket.s3-website.eu-west-3.amazonaws.com:80 resolvers dns check inter 5000

Redirect HTTPS request to HTTP (varnish) and then backend server HTTPS

My current configuration is like this :
1. Nginx listening on Port 8080 and 443
2. Varnish listening to port 80
Currently, when requests are made through HTTP they are delivered through the varnish, but when requests are made through HTTPS varnish doesn't deliver them.
My goal is to put varnish between Client and Nginx web server ( or make varnish work with port 443 )
Reading through articles and answer on StackOverflow, I tried to setup reverse proxy 443 to 80 ( or 8080 maybe ?)
I followed these article(s) :
https://www.smashingmagazine.com/2015/09/https-everywhere-with-nginx-varnish-apache/
https://serverfault.com/questions/835887/redirect-http-to-https-using-varnish-4-1
Problem is that when I try to set these up, I get 502 bad request error, and sometimes the default Nginx page.
PS: I'm trying to set this up using virtual server block, not default server.
PS2: I also need to deliver the final web page through HTTPS weather the request made through HTTP or HTTPS ( but I get too many redirects error )
PS3: I'm using Cloudflare
The basic concept is to sandwich varnish between an entity handling SSL and a back-end server working on port 8080 or whatever you choose.
Here's the traffic flow:
user 443 > front-end proxy for SSL offloading 443 > Varnish 80 > nginx 8080.
Now your options for Front end proxy are:
1.A Load balancer supporting SSL termination / offloading.
2.Nginx or apache working as a proxy to receive traffic on 443 and forward that on port 80 to Varnish.
Error 502 means your Varnish is having issues connecting your backend, please check varnish.vcl

haproxy + nginx get client ip behind anonymous proxy

I'm creating an application, where frontend is Haproxy and nginx.
Do you know a way to get client IP address if navigates behind anonymous proxy with HAproxy ?
My actual configuration for haproxy use "option forwardfor", but I get anonymous proxy IP instead real client IP in nginx logs (using $http_x_forwarded_for var)
frontend general_frontend
bind 111.111.111.111:80
default_backend nginx_farm_backend
backend nginx_farm_backend
balance roundrobin
option abortonclose
option forwardfor
http-check disable-on-404
http-check expect string nginx
option httpchk GET /index.html HTTP/1.0
# - Nodes
server nginx-server-1 222.222.222.222:8080 check on-error mark-down observe layer7 error-limit 1
server nginx-server-1 333.333.333.333:8080 check on-error mark-down observe layer7 error-limit 1
Thank you
Do you Using $remote_addr var for nginx log format?

Reverse proxy Elasticsearch transport port

In my environment, elasticsearch sits on a server that only has standard ports (80, 443, etc.) open. All the other ports are firewalled off. I currently have a reverse proxy on port 80 that reroutes all the elasticsearch HTTP requests to elasticsearch's http port.
I would also like to reroute TCP requests to elasticsearch's transport port, so that my local client can directly query elasticsearch as a client node. Nginx 1.9.0 recently allowed TCP load balancing, which is what I would like to utilize for this, but I'm having some trouble getting my system to work. Here is my nginx.conf file (removed the HTTP context to isolate the issue):
worker_processes 1;
events {
worker_connections 1024;
}
stream {
server {
listen 80;
proxy_pass 127.0.0.1:9300;
}
}
My client node is set up to talk to mydomain.com:80, so it should ideally be routing all traffic to the internal transport port. However, I am getting a the following exceptions: org.elasticsearch.client.transport.NoNodeAvailableException: None of the configured nodes are available
Is there something else I need to configure on my client node or the tcp proxy?
EDIT 1:
Some additional information. I changed Elasticsearch's transport port from 9300 to 8030, which is a port that is open. When I correspondingly changed my nginx.conf to proxypass to 127.0.0.1:8030 my local client node started working, and got appropriate responses to my queries.
So the issue seems to be that if I'm proxy pass to an already open port, it works, but if the port is closed (9300), the proxy pass fails. Does anyone know why this would be and how to fix it? I'd prefer to stick to using port 9300 if possible.

HAProxy connect to backend with source IP

I am running HAProxy on a machine with multiple interfaces and I want the connection to the backend to be made from the source IP of the interface on which the client request came in. Using the source directive from the documentation in the listen blocks didn't seem to do it as all connections seem to come from the first interface. My configuration is as follows:
listen f_192.168.1.10_http
bind 192.168.1.10:80
source 192.168.1.10
mode http
option httplog
capture request header Host len 30
use_backend b_domain1_http if { hdr(host) -i domain1.com }
listen f_192.168.1.20_http
bind 192.168.1.20:80
source 192.168.1.20
mode http
option httplog
capture request header Host len 30
use_backend b_domain1_http if { hdr(host) -i domain1.com }
backend b_domain1_http
mode http
option httplog
server srv1 domain1.com:80 check inter 30s
Ie. I am struggling to get connections coming in on interface 192.168.1.10 to have their source IP be 192.168.1.10 when connecting to the backend. Right now, regardless of if the connection comes in on 192.168.1.10 or 192.168.1.20, the outgoing connection to the backend is initiated from 192.168.1.10. I thought that using source in the listen would accomplish this but when I look at the output of netstat -at, all originating connections to the backend come from 1 interface.
Does anyone have any idea on how I can ensure the source ip of the connection to the backend is the same as the interface of the original client request?
I believe you can use source as a parameter for a server.
backend be1
...
server srv1 domain1.com:80 source ${frontend_ip} check inter 30s
I believe it is possible to substitute %fi for ${frontend_ip}, and you may also use %fp or ${frontend_port} to specifiy the port. This way you can remove the source statements in the frontends.

Resources