Node.js and haproxy - node.js

I use node.js and socket.io.
I have an application that runs on the IP address: 31.31.69.79:3000
I have a domain name: zkus.eu - I want to redirect this domain to this ip: 31.31.69.79:3000
How do I set haproxy config (haproxy.cfg)?

There are several examples on the haproxy site: http://haproxy.1wt.eu/download/1.4/doc/configuration.txt
That said, a fairly minimal config (taken from the examples on that page) is:
global
daemon
maxconn 256
defaults
mode http
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
listen http-in
bind *:80
server server1 127.0.0.1:3000 maxconn 32

Related

HAProxy tcp mode source client ip

I have the following setup in HAProxy
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
defaults
log global
retries 2
option dontlognull
timeout connect 10000
timeout server 600000
timeout client 600000
frontend https
bind 5.x.x.x:443
default_backend https
backend https
mode tcp
balance roundrobin
option tcp-check
server traefik 192.168.128.5:9443 check fall 3 rise 2
And it works as expected, the backend server "traefik" is doing the SSL termination of the requests.
The thing is the client source IP I get in the backend server is the HAProxy's IP and I would like to pass the source IP to the backend server.
Is it possible at all? because I tried all the options I saw in internet.
Thanks.
At the end the solution was to use https://www.haproxy.com/blog/haproxy/proxy-protocol/ as it is supported by HAProxy and traefik.
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
defaults
log global
retries 2
option dontlognull
timeout connect 10000
timeout server 600000
timeout client 600000
frontend https
bind 5.x.x.x:443
default_backend https
backend https
mode tcp
balance roundrobin
option tcp-check
server traefik 192.168.128.5:9443 check fall 3 rise 2 send-proxy
And enabling traefik's entrypoint Proxy Protocol as described here: https://docs.traefik.io/configuration/entrypoints/#proxyprotocol

pfSense + HAProxy – Reverse Proxy with multiple Services on one internal IP

currently I am using pfSense on my server with the HAProxy package, because I can easily configure it via the GUI.
I configured HAProxy to act as a reverse proxy corresponding to this guide: https://blog.devita.co/pfsense-to-proxy-traffic-for-websites-using-pfsense/
SSL offloading works like a charm. The problem I have is when I have more than one service (open port) on the same internal IP it seems not to be working.
Example:
I configure service1.domain.com for Service1 with port 8000 (10.100.10.101:8000) and it works flawlessly.
Now I need another port on the same machine (e.g. 10.100.10.101:8082) with another service. If I configure another backend pointing to the same IP but with a different port I can only reach the second servce (service2.domain.com) even if I access service1.domain.com.
My use case is that I am trying to set up Seafile which is using port 8000 for the web GUI and port 8082 for the fileserver. Right now I am able to access the web GUI but I am not able to upload, download or share files.
My configuration:
# Automaticaly generated, dont edit manually.
# Generated on: 2018-09-29 19:24
global
maxconn 1000
stats socket /tmp/haproxy.socket level admin
gid 80
nbproc 1
hard-stop-after 15m
chroot /tmp/haproxy_chroot
daemon
tune.ssl.default-dh-param 8192
server-state-file /tmp/haproxy_server_state
ssl-default-bind-ciphers TLS13-AES-256-GCM-SHA384:TLS13-AES-128-GCM-SHA256:TLS13-CHACHA20-POLY1305-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
ssl-default-bind-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets
ssl-default-server-ciphers TLS13-AES-256-GCM-SHA384:TLS13-AES-128-GCM-SHA256:TLS13-CHACHA20-POLY1305-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
ssl-default-server-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets
listen HAProxyLocalStats
bind 127.0.0.1:2200 name localstats
mode http
stats enable
stats admin if TRUE
stats show-legends
stats uri /haproxy/haproxy_stats.php?haproxystats=1
timeout client 5000
timeout connect 5000
timeout server 5000
frontend shared-frontend-merged
bind X.X.X.X:443 name X.X.X.X:443 ssl crt-list /var/etc/haproxy/shared-frontend.crt_list
mode http
log global
option http-keep-alive
option forwardfor
acl https ssl_fc
http-request set-header X-Forwarded-Proto http if !https
http-request set-header X-Forwarded-Proto https if https
timeout client 30000
http-response set-header Strict-Transport-Security max-age=15768000
acl aclcrt_shared-frontend var(txn.txnhost) -m reg -i ^([^\.]*)\.domain\.com(:([0-9]){1,5})?$
acl ACL1 var(txn.txnhost) -m str -i test.domain.com
acl ACL2 var(txn.txnhost) -m str -i service1.domain.com
acl ACL3 var(txn.txnhost) -m str -i service2.domain.com
http-request set-var(txn.txnhost) hdr(host)
default_backend test.domain.com_ipv4
default_backend service1.domain.com_ipvANY
default_backend service2.domain.com_ipvANY
frontend http-to-https
bind X.X.X.X:80 name X.X.X.X:80
mode http
log global
option http-keep-alive
timeout client 30000
http-request redirect scheme https
backend test.domain.com_ipv4
mode http
id 10100
log global
timeout connect 30000
timeout server 30000
retries 3
source ipv4# usesrc clientip
option httpchk GET /
server testvm-server01 10.100.10.101:54080 id 10101 check inter 1000
backend service1.domain.com_ipvANY
mode http
id 102
log global
timeout connect 30000
timeout server 30000
retries 3
option httpchk GET /
server seafile-vm-01 10.100.10.103:8000 id 101 check inter 1000
backend service2.domain.com_ipvANY
mode http
id 104
log global
timeout connect 30000
timeout server 30000
retries 3
option httpchk GET /
server seafile-vm-02 10.100.10.103:8082 id 103 check inter 1000
I would really be glad if anyone can point me in the right direction, thank you in advance and if you need further information please tell me.
Best regards,
Bioneye
I was able to solve my problem with the help of one awesome user over on reddit.
The first problem was that I misconfigured my frontend and thus had 3 default_backends. That was the reason why every services pointed to the same virtual machine. To solve it I just had to add the if condition corresponding to my ACL name.
The second problem was that my Service2 was shown as DOWN on the HAProxy stats page. I had to change the health check method from HTTP to Basic and that finally resolved everything.
This is the working configuration:
# Automaticaly generated, dont edit manually.
# Generated on: 2018-10-02 16:59
global
maxconn 1000
stats socket /tmp/haproxy.socket level admin
gid 80
nbproc 1
hard-stop-after 15m
chroot /tmp/haproxy_chroot
daemon
tune.ssl.default-dh-param 8192
server-state-file /tmp/haproxy_server_state
ssl-default-bind-ciphers TLS13-AES-256-GCM-SHA384:TLS13-AES-128-GCM-SHA256:TLS13-CHACHA20-POLY1305-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
ssl-default-bind-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets
ssl-default-server-ciphers TLS13-AES-256-GCM-SHA384:TLS13-AES-128-GCM-SHA256:TLS13-CHACHA20-POLY1305-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
ssl-default-server-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets
listen HAProxyLocalStats
bind 127.0.0.1:2200 name localstats
mode http
stats enable
stats admin if TRUE
stats show-legends
stats uri /haproxy/haproxy_stats.php?haproxystats=1
timeout client 5000
timeout connect 5000
timeout server 5000
frontend shared-frontend-merged
bind X.X.X.X:443 name X.X.X.X:443 ssl crt-list /var/etc/haproxy/shared-frontend.crt_list
mode http
log global
option http-keep-alive
option forwardfor
acl https ssl_fc
http-request set-header X-Forwarded-Proto http if !https
http-request set-header X-Forwarded-Proto https if https
timeout client 30000
http-response set-header Strict-Transport-Security max-age=15768000
acl aclcrt_shared-frontend var(txn.txnhost) -m reg -i ^([^\.]*)\.domain\.com(:([0-9]){1,5})?$
acl ACL1 var(txn.txnhost) -m beg -i test.domain.com
acl ACL2 var(txn.txnhost) -m beg -i service1.domain.com
acl ACL3 var(txn.txnhost) -m beg -i service2.domain.com
http-request set-var(txn.txnhost) hdr(host)
use_backend test.domain.com_ipv4 if ACL1
use_backend service1.domain.com_ipvANY if ACL2
use_backend service2.domain.com-seafhttp_ipvANY if ACL3
frontend http-to-https
bind X.X.X.X:80 name X.X.X.X:80
mode http
log global
option http-keep-alive
timeout client 30000
http-request redirect scheme https
backend test.domain.com_ipv4
mode http
id 10100
log global
timeout connect 30000
timeout server 30000
retries 3
source ipv4# usesrc clientip
option httpchk GET /
server testvm-server01 10.100.10.101:54080 id 10101 check inter 1000
backend service1.domain.com_ipvANY
mode http
id 102
log global
timeout connect 30000
timeout server 30000
retries 3
option httpchk GET /
server seafile-vm-01 10.100.10.103:8000 id 101 check inter 1000
backend service2.domain.com-seafhttp_ipvANY
mode http
id 104
log global
timeout connect 30000
timeout server 30000
retries 3
server seafile-vm-02 10.100.10.103:8082 id 103 check inter 1000
For further details: https://www.reddit.com/r/PFSENSE/comments/9kezl3/pfsense_haproxy_reverse_proxy_with_multiple/?st=jmruoa9r&sh=26d24791
TLDR: I misconfigured my Action Table and had the wrong health check in place.
Greetings,
Bioneye

HAProxy error on OpenShift - Failed to execute: 'control restart'

I am trying to configure HAProxy on OpenShift to achieve following URL based routing.
when I am trying to restart my app, I am getting following error in HAProxy log
Starting frontend http-in: cannot bind socket
Following are the changes I made to haproxy.cfg, in addition I have also added "user nobody" to global section. What am I doing wrong? I am new to HAProxy, so I believe it might be very basic thing I am missing.
frontend http-in
bind :80
acl is_blog url_beg /blog
use_backend blog_gear if is_blog
default_backend website_gear
backend blog_gear
mode http
balance roundrobin
option httpchk
option forwardfor
server WEB1 nodejs-realspace.rhcloud.com weight 1 maxconn 512 check
backend website_gear
mode http
balance roundrobin
option httpchk
option forwardfor
server WEB2 website-realspace.rhcloud.com weight 1 maxconn 512 check
To note a few problems with your configuration.
The first problem in your configuration is that you should listen on port 8080.
Ports 80, 443, 8000 an 8443 on the outside will be redirected to port 8080 on your gear.
Second website-realspace.rhcloud.com is probably the external name of your gear that also hosts your HAProxy. This means that you have created a loop.
To acces your nodejs app you'll need to use the 127.a.b.c address assigned to your gear.
Also your nodejs app should most likely cannot listen on the same port as your HAProxy.

HAProxy + Nodejs + SockJS + Express + SSL

I've got a server setup in NodeJS which looks like the picture below:
Now what i want to do two things which seem to be possible with HAProxy:
To only use one port no matter what server a client wants to access. I want to use the external port 8080 for all non SSL
traffic. (All SSL traffic should use the port 443)
Enable SSL on the SockJS Server and the Express Server.
Please not that all my servers are running on the same instance on an amazon ec2. So i want to internally route the traffic.
This is my haproxy.cfg so far:
mode http
# Set timeouts to your needs
timeout client 10s
timeout connect 10s
timeout server 10s
frontend all 0.0.0.0:8080
mode http
timeout client 120s
option forwardfor
# Fake connection:close, required in this setup.
option http-server-close
option http-pretend-keepalive
acl is_sockjs path_beg /echo /broadcast /close
acl is_stats path_beg /stats
use_backend sockjs if is_sockjs
use_backend stats if is_stats
default_backend express
backend sockjs
# Load-balance according to hash created from first two
# directories in url path. For example requests going to /1/
# should be handled by single server (assuming resource prefix is
# one-level deep, like "/echo").
balance uri depth 2
timeout server 120s
server srv_sockjs1 127.0.0.1:8081
backend express
balance roundrobin
server srv_static 127.0.0.1:8008
backend stats
stats uri /stats
stats enable
Cant figure out how to route the SSL and the traffic to the TCP Server (8080 internal port)
Any ideas?
Your setup is kinda hard to understand (for me). If I understand your goals correctly, you want to serve your web service through SSL hence port 443. And from 443, connect to port 8080 (internally). If that is the case then the following configuration might be what you are looking for. It does not really use port 8080 but instead it connects directly to your express backend. You don't really need to have port 8080 exposed (unless you have special reasons for doing so) because you can just use the backend servers directly inside the frontend section.
Note that this only works for HAProxy 1.5+, if you are using older version of HAProxy, you should put something to tunnel the SSL connection before it reaches HAProxy (But I strongly suggest 1.5 because it makes your setup less complex)
frontend ssl
bind *:443 ssl crt /path/to/cert.pem ca-file /path/to/cert.pem
timeout client 120s
option forwardfor
# Fake connection:close, required in this setup.
option http-server-close
option http-pretend-keepalive
acl is_sockjs path_beg /echo /broadcast /close
acl is_stats path_beg /stats
use_backend sockjs if is_sockjs
use_backend stats if is_stats
default_backend express

HAproxy and Node.js+Spdy

I'm currently using node spdy to serve files. This works beautifully.
However I would like to use HAproxy to load balance amongst these node servers. But when my node/spdy server is behind HAproxy, request.isSpdy is false... so spdy is all of a sudden not supported?
Here's my HAproxy configuration:
global
maxconn 4096
defaults
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
frontend http_proxy
mode http
bind *:80
redirect prefix https://awesome.com code 301
frontend https_proxy
mode tcp
bind *:443
default_backend webservers
backend webservers
balance source
server server1 127.0.0.1:10443 maxconn 4096
# server server2 127.0.0.1:10444 maxconn 4096
Thanks!
You can't use HAProxy's HTTP load balancing mechanism with SPDY. First, you need to use the latest development branch to enable support for NPN (and hence SPDY), and after that, you will have to configure it to run closer to simple TCP load-balancing mode -- HAProxy does not understand SPDY.
For an example HAProxy + SPDY config script, see here:
http://www.igvita.com/2012/10/31/simple-spdy-and-npn-negotiation-with-haproxy/
I ran into this same issue. Instead of using spdy, I went back to using express and made haproxy use the http/2 protocol.
frontend http-in
bind *:80
mode http
redirect scheme https code 301
frontend https-in
mode http
bind *:443 ssl crt /path/to/cert.pem alpn h2,http/1.1
the key here is this part alpn h2,http/1.1

Resources