Search code examples
tcpload-balancinghaproxy

how to loadbalance tcp on haproxy


I have a tcp service running on port 8080 on 3 servers behind haproxy i will like to loadbalance the tcp traffic between these servers via haproxy

server1 192.168.10.1 8080
server2 192.168.10.2 8080
server3 192.168.10.3 8080

lets say haproxy server ip is 192.168.10.10

1.

what haproxy configuration can i use to achieve this? what will be the endpoint to access the loadbalanced tcp traffic after the config is made active?

2.

one other thing is, is it possible to proxy that endpoint to like a url without a port? similar to http based routing...so can i then put that tcp endpoint and have a way to route an http endpoint via hostname to the loadbalanced tcp service?

so lets say i wan to access the service at http://tcp-app.example.com and then should be routed to the loadbalanced tcp service


Solution

  • To Answer 1 can you use this as start point

    listen tcp-in
      bind :8080
    
      mode tcp
      log stdout format raw daemon
      option tcplog
    
      timeout client   5s
      timeout connect 30s
      timeout server  30s
    
      server server1 192.168.10.1:8080
      server server2 192.168.10.2:8080
      server server3 192.168.10.3:8080
    

    You can the reach the loadbalancer via 192.168.10.10:8080.
    For better understanding of haproxy this blog post a good start point IMHO
    https://www.haproxy.com/blog/the-four-essential-sections-of-an-haproxy-configuration/

    For question 2 should you switch to Server Name Indication (SNI) because TCP have not the concept of "Hostnames".
    I have described how SNI routing works in HAProxy in this blog post https://www.me2digital.com/blog/2019/05/haproxy-sni-routing/

    Here a example haproxy config for SNI Routing between TCP and HTTP protocol. It's a little bit complex because you will need to check the TCP routing before the HTTP routing.

    #---------------------------------------------------------------------
    # Global settings
    #---------------------------------------------------------------------
    global
        log stdout format raw daemon debug
    
        maxconn     5000
    
        tune.ssl.default-dh-param 3072
    
        # https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=haproxy-1.8.0&openssl=1.1.0i&hsts=yes&profile=modern
        # set default parameters to the intermediate configuration
        ssl-default-bind-ciphers 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 ssl-min-ver TLSv1.1 no-tls-tickets
    
        ssl-default-server-ciphers 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 ssl-min-ver TLSv1.1 no-tls-tickets
        
        # https://www.haproxy.com/blog/dynamic-configuration-haproxy-runtime-api/
        stats socket ipv4@127.0.0.1:9999 level admin
        stats socket /var/run/haproxy.sock mode 666 level admin
        stats timeout 2m
    
    #---------------------------------------------------------------------
    # common defaults that all the 'listen' and 'backend' sections will
    # use if not designated in their block
    #---------------------------------------------------------------------
    defaults
        mode                    tcp
        log                     global
        option                  dontlognull
        #option                  logasap
        option                  srvtcpka
        option                  log-separate-errors
        retries                 3
        timeout http-request    10s
        timeout queue           2m
        timeout connect         10s
        timeout client          5m
        timeout server          5m
        timeout http-keep-alive 10s
        timeout check           10s
        maxconn                 750
    
    #---------------------------------------------------------------------
    # main frontend which proxys to the backends
    #---------------------------------------------------------------------
    
    ##
    ## Frontend for HTTP
    ##
    frontend http-in
        bind :::80 v4v6
        mode http
        option httplog
    
        tcp-request inspect-delay 5s
        tcp-request content accept if HTTP
    
        # redirect http to https .
        http-request redirect scheme https unless { ssl_fc }
    
    ##
    ## Frontend for HTTPS
    ##
    frontend public_ssl
    
        bind :::443 v4v6 
    
        option tcplog
    
        tcp-request inspect-delay 5s
        tcp-request content capture req.ssl_sni len 25
        tcp-request content accept if { req.ssl_hello_type 1 }
        
        # https://www.haproxy.com/blog/introduction-to-haproxy-maps/
        use_backend %[req.ssl_sni,lower,map(tcp-domain2backend-map.txt)]
    
        default_backend be_sni
    
    ##########################################################################
    # TLS SNI
    #
    # When using SNI we can terminate encryption with dedicated certificates.
    ##########################################################################
    backend be_sni
      server fe_sni 127.0.0.1:10444 weight 10 send-proxy-v2-ssl-cn
    
    backend be_sni_xmpp
      server li_tcp-in 127.0.0.1:8080 weight 10 send-proxy-v2-ssl-cn
    
    # handle https incoming
    frontend https-in
    
        # terminate ssl 
        bind 127.0.0.1:10444 accept-proxy ssl strict-sni alpn h2,http/1.1 crt haproxy-certs
    
        mode http
        option forwardfor
        option httplog
        option http-ignore-probes
    
        # Strip off Proxy headers to prevent HTTpoxy (https://httpoxy.org/)
        http-request del-header Proxy
    
        http-request set-header Host %[req.hdr(host),lower]
        http-request set-header X-Forwarded-Proto https
        http-request set-header X-Forwarded-Host %[req.hdr(host),lower]
        http-request set-header X-Forwarded-Port %[dst_port]
        http-request set-header X-Forwarded-Proto-Version h2 if { ssl_fc_alpn -i h2 }
        http-request add-header Forwarded for=\"[%[src]]\";host=%[req.hdr(host),lower];proto=%[req.hdr(X-Forwarded-Proto)];proto-version=%[req.hdr(X-Forwarded-Proto-Version)]
    
        # Add hsts https://www.haproxy.com/blog/haproxy-and-http-strict-transport-security-hsts-header-in-http-redirects/
        # http-response set-header Strict-Transport-Security "max-age=16000000; includeSubDomains; preload;"
    
        # https://www.haproxy.com/blog/introduction-to-haproxy-maps/
        use_backend %[req.hdr(host),lower,map(http-domain2backend-map.txt)]
    
    #---------------------------------------------------------------------
    #  backends
    #---------------------------------------------------------------------
    ## backend for cloud.DOMAIN
    backend nextcloud-backend
        mode http
        option httpchk GET / HTTP/1.1\r\nHost:\ BACKEND_VHOST
        server short-cloud 127.0.0.1:81 check 
    
    
    ## backend for dashboard.DOMAIN
    backend dashboard-backend
        mode http
        server short-cloud 127.0.0.1:82 check
    
    ## backend for upload.DOMAIN
    backend httpupload-backend
        log global
        mode http
        server short-cloud 127.0.0.1:8443 check
    
    listen tcp-in
      bind :8080 accept-proxy ssl strict-sni crt haproxy-certs
    
      mode tcp
      log stdout format raw daemon
      option tcplog
    
      timeout client   5s
      timeout connect 30s
      timeout server  30s
    
      server server1 192.168.10.1:8080
      server server2 192.168.10.2:8080
      server server3 192.168.10.3:8080
    

    File tcp-domain2backend-map.txt

    tcp-service.mydomain.im be_sni_xmpp
    

    File http-domain2backend-map.txt

    # http backends
    nextcloud.MyDomain.com nextcloud-backend
    dashboard.MyDomain.com dashboard-backend 
    jabupload.MyDomain.com httpupload-backend