Quantcast
Channel: HAProxy community - Latest topics
Viewing all articles
Browse latest Browse all 4730

Port forward all http(s) to haproxy for SNI with LE/nginx, and restrict some TCP/mysql access per IP

$
0
0

I have an OpenWRT firewall which is configured to send all 80/443 to HAproxy.

I use pihole for local DNS/DHCP

I then use an HAproxy LXC to route the requests to other VM/LXC’s in my LAN (proxmox VE + a few pi’s).

I also want to restrict mysql access to specific whitelisted IP’s which are in a file (/etc/haproxy/whitelist.IPs) for specific CLI tasks. They connect to <public_IP>:33061 where HAproxy has a listener and routes to mysql:3306 if the srcIP is in the whitelist (the whitelist gets a DynDNS update using dig as needed)

At the moment I use LE wildcard certs and nginx(SSL) for the https but that means I have multiple places to update certificates and configs, and the wildcard LE via DNS is messy, so what I’d like to do is switch it to HAproxy issued certs which also get updated as needed by the HAproxy machine.
I understand that only need to have a specific LE port change and a PEM concat for HAproxy, but what I am not getting right is the syntax for the FE/BE within haproxy.cfg

The one I can’t get right is the jellyfin one, so I did a workaround on port forwards and those requests go to a non-80/443 port which bypass HAproxy and gets sent straight to the JF:8096 machine’s nginx reverse proxy - I’d like to have pretty much all traffic going via HAproxy.

This sometime works and sometimes does’t even though the configs look the same to me (which also goes to show that I don’t really know what I am doing :blush: )
My config looks like below… and does (mostly) work - but feels like it’s horribly ugly/inefficient.
{sorry if it’s weirdly spaced because of the IDE I used}

What should I add/del/change to make it more robust and closer to better/best practices?
My aim…

  • HAproxy manages all certs (auto updates as well as new and with A+ ssl ratings if possible)
  • I’d like to be able to see/detect client IP’s at the nginx/httpd point
  • nginx only needs to be set for the basic http:80 since the rest is done higher up
  • fix the mangle for jellyfin so that it can come in via 80/443 and get to the JF-reverse-proxy correctly…and show the client IP in there too
  • when I add in check for some of the BE’s they fail in the stats - I don’t understand where/why (I did try putting in hosts entries on the HAproxy machine, and also in the pihole-DNS for those but it didn’t help).

Thanks in advance. I don;t take offense so if I need to get flamed, that’s OK

global
  log       /dev/log  local0
  log       /dev/log  local1 notice
  # https://www.haproxy.com/blog/introduction-to-haproxy-logging/
  chroot    /var/lib/haproxy
  stats     socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
  stats     timeout 30s

  user      haproxy
  group     haproxy
  daemon
  # Default SSL material locations
  ca-base   /etc/ssl/certs
  crt-base  /etc/ssl/private

  # See: https://ssl-config.mozilla.org/#server=haproxy&version=2.6&config=modern&openssl=1.1.1n&guideline=5.6
  # modern configuration
  ssl-default-bind-ciphersuites   TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
  ssl-default-bind-options        prefer-client-ciphers no-sslv3 no-tlsv10 no-tlsv11 no-tlsv12 no-tls-tickets
  ssl-default-server-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
  ssl-default-server-options      no-sslv3 no-tlsv10 no-tlsv11 no-tlsv12 no-tls-tickets
  ssl-default-server-ciphers      ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
  tune.ssl.default-dh-param 2048

defaults
  log       global
  option    httplog
  option    dontlognull
  # option    forwardfor       except 127.0.0.0/8
  option    redispatch
  option    http-server-close
  retries   3
  timeout   http-request    10s
  timeout   queue           1m
  timeout   connect         10s
  timeout   client          1m
  timeout   server          1m
  timeout   http-keep-alive 10s
  # timeout   check           10s
  # maxconn   3000
  errorfile 400 /etc/haproxy/errors/400.http
  errorfile 403 /etc/haproxy/errors/403.http
  errorfile 408 /etc/haproxy/errors/408.http
  errorfile 500 /etc/haproxy/errors/500.http
  errorfile 502 /etc/haproxy/errors/502.http
  errorfile 503 /etc/haproxy/errors/503.http
  errorfile 504 /etc/haproxy/errors/504.http

frontend stats
  bind                *:9000
  mode                http
  stats               enable
  stats               uri /stats
  stats               refresh 30s
  stats               auth admin:password
  stats               hide-version
  stats               realm HAproxy\ Statistics

frontend http_in
  bind                *:80 alpn h2,h2c,http/1.1
  mode                http
  option              forwardfor
  http-request        redirect scheme https unless { ssl_fc }
  # All of the rules applying on port 80 (or any port) need to be specified on a single frontend (or a single listen) that is bound to port 80. [https://serverfault.com/questions/794943/haproxy-multiple-frontends-same-bind]

frontend https_in
  bind                *:443
  mode                tcp
  option              tcplog
  tcp-request         inspect-delay 5s

  acl tls             req_ssl_hello_type 1
  tcp-request         content accept if tls
  # tcp-request         content accept if { req_ssl_hello_type 1 }      ### this line does the same as the 2 above it

  option forwardfor   header X-Real-IP
  http-request        set-header X-Real-IP %[src]
  HSTS (63072000 seconds)
  http-response set-header Strict-Transport-Security max-age=63072000

  acl acl_jellyfin     req_ssl_sni   -i jellyfin.example.org
  acl acl_nextcloud    req_ssl_sni   -i nextcloud.example.org
  acl acl_httpd        req_ssl_sni   -i httpd.example.org
  acl acl_serene       req_ssl_sni   -i serene.example.org
  acl acl_serene       req_ssl_sni   -i serene.example.net

  use_backend         nextcloud  if acl_nextcloud
  use_backend         httpd      if acl_httpd
  use_backend         jellyfin   if acl_jellyfin
  use_backend         serene     if acl_serene
  default_backend     default

backend httpd
  mode        tcp
  #option      httplog
  option      tcp-check
  option      ssl-hello-chk
  option      httpchk GET /
  http-check  send hdr Host httpd.example.org
  server      httpd         httpd.example.org:443 check-ssl verify none send-proxy-v2

backend nextcloud
  mode        tcp
  # http-check expect status 200  #* when I specify the code 200, HAproxy reports "no backend server available" - seems that it's better to let it work out the code itself
  option      tcp-check
  option      ssl-hello-chk
  option      httpchk GET /
  http-check  send hdr  Host nextcloud.example.org
  server      nextcloud      nextcloud.example.org:443 check-ssl verify none check-sni nextcloud.example.org sni str(nextcloud.example.org) # send-proxy-v2

backend jellyfin
  mode        tcp
  # http-check  send hdr Host jellyfin.example.org
  option      tcp-check
  option      ssl-hello-chk
  option      httpchk GET /
  server      jellyfin      jellyfin.example.org:443 check-ssl verify none send-proxy-v2

backend serene
  mode        tcp
  option      tcp-check
  option      ssl-hello-chk
  option      httpchk GET /
  http-check  send hdr Host serene.example.org
  server      serene        serene.example.org:443 check-ssl verify none send-proxy-v2

backend default
  mode        tcp
  option      tcp-check
  option      ssl-hello-chk
  option      httpchk GET /
  http-check  send hdr Host wotd.example.org
  server      nginx         wotd.example.org:443 check-ssl verify none send-proxy-v2

listen mysql
  bind        <public_IP>:33061
  mode        tcp
  acl         mysql_ip_OK src -f /etc/haproxy/whitelist.IPs
  tcp-request connection reject if !mysql_ip_OK
  balance     roundrobin
    # I am using 127.0.0.1/localhost as the "list" of servers for the sake of example - real world would be the IP list of actual server IPs
    server    mysql1 127.0.0.1:3306
    server    mysql2 localhost:3306

1 post - 1 participant

Read full topic


Viewing all articles
Browse latest Browse all 4730

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>