haproxy question about: dual stack / authentication



  • Hi,
    I got some questions regarding the haproxy package:

    1. I would like the client with an IPv4 address to send to a different backend than the one with an IPv6 address. How is this possible?
    2. There are websites only authorized people should be able to access. Since I cannot packet filter I would like to make use of some sort of authentication. I have an LDAP (FreeIPA) running in my network so ideally I would like to make use of that. Is that possible? If authentication is not an option, can I restrict access to specific haproxy frontends to specific IPv6 prefixes?
    3. How can I make a simple redirect? sub1.domain1.net is going to sub2.domain1.net.

    This is my config:

    global
            maxconn                 10000
            stats socket /tmp/haproxy.socket level admin
            uid                     80
            gid                     80
            nbproc                  1
            hard-stop-after         15m
            chroot                          /tmp/haproxy_chroot
            daemon
            tune.ssl.default-dh-param       2048
            server-state-file /tmp/haproxy_server_state
    
    listen HAProxyLocalStats
            bind 127.0.0.1:22221 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                    2001:fdd0:1:4f::6:80 name 2001:fdd0:1:4f::6:80   ssl crt-list /var/etc/haproxy/shared_frontend.crt_list
            bind                    2001:fdd0:1:4f::6:443 name 2001:fdd0:1:4f::6:443   ssl crt-list /var/etc/haproxy/shared_frontend.crt_list
            bind                    1.23.45.6:80 name 1.23.45.6:80   ssl crt-list /var/etc/haproxy/shared_frontend.crt_list
            bind                    1.23.45.6:443 name 1.23.45.6: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
            acl                     aclcrt_shared_frontend  var(txn.txnhost) -m reg -i ^media\.domain1.net\.net(:([0-9]){1,5})?$
            acl                     acl1_domain4   var(txn.txnhost) -m str -i map.domain4.de
            acl                     aclcrt_map.domain4.de  var(txn.txnhost) -m reg -i ^map\.domain4\.de(:([0-9]){1,5})?$
            acl                     acl1    var(txn.txnhost) -m str -i media.domain1.net
            acl                     aclcrt_media.domain1.net   var(txn.txnhost) -m reg -i ^media\.domain1.net\.net(:([0-9]){1,5})?$
            acl                     acl1    var(txn.txnhost) -m str -i domain5.de
            acl                     aclcrt_domain5.de var(txn.txnhost) -m reg -i ^domain5\.de(:([0-9]){1,5})?$
            acl                     acl1    var(txn.txnhost) -m str -i ah.domain5.de
            acl                     aclcrt_ah.domain5.de      var(txn.txnhost) -m reg -i ^ah\.domain5\.de(:([0-9]){1,5})?$
            acl                     acl1    var(txn.txnhost) -m str -i db.unix.domain2.net
            acl                     aclcrt_db.unix.domain2.net        var(txn.txnhost) -m reg -i ^db\.unix\.domain2\.net(:([0-9]){1,5})?$
            acl                     acl1    var(txn.txnhost) -m str -i git.unix.domain2.net
            acl                     aclcrt_git.unix.domain2.net       var(txn.txnhost) -m reg -i ^git\.unix\.domain2\.net(:([0-9]){1,5})?$
            acl                     acl1    var(txn.txnhost) -m str -i gestioip.domain1.net
            acl                     aclcrt_gestioip.domain1.net        var(txn.txnhost) -m reg -i ^gestioip\.domain1.net\.net(:([0-9]){1,5})?$
            acl                     acl1    var(txn.txnhost) -m str -i domain3.de
            acl                     acl2    var(txn.txnhost) -m str -i www.domain3.de
            acl                     aclcrt_kabeljochen.de   var(txn.txnhost) -m reg -i ^domain3\.de(:([0-9]){1,5})?$
            acl                     aclcrt_kabeljochen.de   var(txn.txnhost) -m reg -i ^www\.domain3\.de(:([0-9]){1,5})?$
            acl                     acl1    var(txn.txnhost) -m str -i gosix.domain1.net
            acl                     aclcrt_gosix.domain1.net   var(txn.txnhost) -m reg -i ^gosix\.domain1.net\.net(:([0-9]){1,5})?$
            acl                     acl1    var(txn.txnhost) -m str -i ideas.domain1.net
            acl                     aclcrt_ideas.domain1.net   var(txn.txnhost) -m reg -i ^ideas\.domain1.net\.net(:([0-9]){1,5})?$
            acl                     acl1    var(txn.txnhost) -m str -i wiki.domain1.net
            acl                     aclcrt_wiki.domain1.net    var(txn.txnhost) -m reg -i ^wiki\.domain1.net\.net(:([0-9]){1,5})?$
            acl                     acl1    var(txn.txnhost) -m str -i riot.domain1.net
            acl                     aclcrt_riot.domain1.net    var(txn.txnhost) -m reg -i ^riot\.domain1.net\.net(:([0-9]){1,5})?$
            acl                     acl1    var(txn.txnhost) -m str -i db.domain1.net
            acl                     aclcrt_db.domain1.net      var(txn.txnhost) -m reg -i ^db\.domain1.net\.net(:([0-9]){1,5})?$
            acl                     acl1    var(txn.txnhost) -m str -i ip.domain1.net
            acl                     aclcrt_ip.domain1.net      var(txn.txnhost) -m reg -i ^images\.domain1.net\.net(:([0-9]){1,5})?$
            http-request set-var(txn.txnhost) hdr(host)
            use_backend srv108_map_domain4_ipvANY  if   aclcrt_map.domain4.de
            use_backend emby.unix.domain2.net_ipvANY  if   aclcrt_media.domain1.net
            use_backend domain5.de_ipvANY  if   aclcrt_domain5.de
            use_backend srv123.unix.domain2.net-ah.domain5.de_ipvANY  if   aclcrt_ah.domain5.de
            use_backend db.unix.domain2.net_ipvANY  if   aclcrt_db.unix.domain2.net
            use_backend git.unix.domain2.net_ipvANY  if   aclcrt_git.unix.domain2.net
            use_backend gestioip_srv119_ipvANY  if   aclcrt_gestioip.domain1.net
            use_backend kabeljochen_srv119_ipvANY  if   aclcrt_kabeljochen.de
            use_backend gosix.domain1.net_srv119_ipvANY  if   aclcrt_gosix.domain1.net
            use_backend ideas.domain1.net_srv119_ipvANY  if   aclcrt_ideas.domain1.net
            use_backend wiki.domain1.net_srv119_ipvANY  if   aclcrt_wiki.domain1.net
            use_backend riot.domain1.net_srv119_ipvANY  if   aclcrt_riot.domain1.net
            use_backend db.unix.domain2.net_ipvANY  if   aclcrt_db.domain1.net
            use_backend ip.domain1.net_srv119_ipvANY  if   aclcrt_ip.domain1.net
    
    frontend http_to_https
            bind                    1.23.45.6:80 name 1.23.45.6:80
            bind                    2001:fdd0:1:4f::6:80 name 2001:fdd0:1:4f::6:80
            mode                    http
            log                     global
            option                  http-keep-alive
            timeout client          30000
            http-request redirect scheme https
    
    backend srv108_map_domain4_ipvANY
            mode                    http
            id                      102
            log                     global
            timeout connect         30000
            timeout server          30000
            retries                 3
            server                  srv108.domain2.net 2001:fdd0:3f:1::6:8123 id 103 check inter 10000
    
    backend emby.unix.domain2.net_ipvANY
            mode                    http
            id                      100
            log                     global
            balance                 leastconn
            timeout connect         30000
            timeout server          30000
            retries                 3
            option                  httpchk OPTIONS /
            server                  emby.unix.domain2.net_0 10.10.101.59:8096 check inter 10000
            server                  emby.unix.domain2.net_1 2009:4444:28d4:1b:d313:1726:1a3b:b596:8096 check inter 10000
    
    backend domain5.de_ipvANY
            mode                    http
            id                      104
            log                     global
            timeout connect         30000
            timeout server          30000
            retries                 3
            server                  srv118.domain2.net 2001:fdd0:3f:6::6:8008 id 105 check inter 10000
    
    backend srv123.unix.domain2.net-ah.domain5.de_ipvANY
            mode                    http
            id                      106
            log                     global
            timeout connect         30000
            timeout server          30000
            retries                 3
            server                  srv123.unix.domain2.net 2001:fdd0:3f:7::5:8080 id 105 check inter 10000
            
    backend db.unix.domain2.net_ipvANY
            mode                    http
            id                      107
            log                     global
            timeout connect         30000
            timeout server          30000
            retries                 3
            server                  mariadb.domain2.net 2001:fdd0:3f:5::4:80 id 105 check inter 10000
    
    backend git.unix.domain2.net_ipvANY
            mode                    http
            id                      108
            log                     global
            timeout connect         30000
            timeout server          30000
            retries                 3
            server                  srv104.domain2.net_gogs_0 5.145.135.92:3000 check inter 10000
            server                  srv104.domain2.net_gogs_1 2001:fdd0:3f::4:3000 check inter 10000
    
    backend gestioip_srv119_ipvANY
            mode                    http
            id                      109
            log                     global
            timeout connect         30000
            timeout server          30000
            retries                 3
            server                  srv119_gestioip 2001:fdd0:3f::7:80 id 105 check inter 10000
    
    backend kabeljochen_srv119_ipvANY
            mode                    http
            id                      110
            log                     global
            timeout connect         30000
            timeout server          30000
            retries                 3
            option                  httpchk OPTIONS /
            server                  srv119_kabeljochen 2001:fdd0:3f::8:80 id 105 check inter 10000
    
    backend gosix.domain1.net_srv119_ipvANY
            mode                    http
            id                      111
            log                     global
            timeout connect         30000
            timeout server          30000
            retries                 3
            option                  httpchk OPTIONS /
            server                  srv119_gosix.domain1.net 2001:fdd0:3f::9:80 id 105 check inter 10000
            
    backend ideas.domain1.net_srv119_ipvANY
            mode                    http
            id                      112
            log                     global
            timeout connect         30000
            timeout server          30000
            retries                 3
            option                  httpchk OPTIONS /
            server                  srv119_ideas.domain1.net 2001:fdd0:3f::a:80 id 105 check inter 10000
    
    backend wiki.domain1.net_srv119_ipvANY
            mode                    http
            id                      115
            log                     global
            timeout connect         30000
            timeout server          30000
            retries                 3
            server                  srv119_wiki.domain1.net 2001:fdd0:3f::e:80 id 105 check inter 10000
    
    backend riot.domain1.net_srv119_ipvANY
            mode                    http
            id                      116
            log                     global
            timeout connect         30000
            timeout server          30000
            retries                 3
            option                  httpchk OPTIONS /
            server                  srv119_riot.domain1.net 2001:fdd0:3f::f:80 id 105 check inter 10000
    
    backend ip.domain1.net_srv119_ipvANY
            mode                    http
            id                      114
            log                     global
            timeout connect         30000
            timeout server          30000
            retries                 3
            option                  httpchk OPTIONS /
            server                  srv119_ip.domain1.net 2001:fdd0:3f::d:80 id 105 check inter 10000
    


  • @pmisch

    1. you could create a acl for this together with the use_backend action. The acl would check something like matching for a sourceip of: "0.0.0.0/0" and if that matches use the IPv4 backend..

    2. you can create a list of hosts&networks in the pfSense/firewall/aliases and define a ACL for the source-ip to be present in that list. It should be possible to mix both your allowed ipv6 and ipv4 client addresses in that list.

    3. it is possible to create a 'action' to perform a 'http-request redirect' put in the 'rule' something like "location https://sub2.domain1.net/" and of course add the acl name with the rule to check for the 'hostname matches' 'sub1.domain1.net'



  • I tried 1. and I cannot find a way to make it work. I end up with two frontend definitions. There's one for IPv4 where I say
    Source IP matches IP or alias 0.0.0.0/0
    and there's one frontend where I say
    Source IP machtes IP or alias ::/0
    Both frontends have a different backend chosen.
    The problem seems to be that any given IPv4 address also matches to ::/0 in haproxy. As a dirty workaround I started using 2003::/3 for the acl. That works.
    Point 2. and 3. also worked fine after some experimenting. Thank you very much.



  • @pmisch
    For 1. , creating the ACL is only half the job, you must use it to perform the proper 'action' where you would put a 'use_backend' action that will be performed if the acl matches.

    Something like this effectively:

    acl request_is_made_over_ipv4 src 0.0.0.0/0
    use_backend MyIPv4backend if request_is_made_over_ipv4
    use_backend MyIPv6backend if !request_is_made_over_ipv4
    


  • Thank you @PiBA. I changed my actions so that they use the ACLs. Works quite nicely.
    Regarding IP Filter / Authentication I found this article:
    https://hochwald.net/user-authentication-with-haproxy-on-pfsense/
    I have not tried it, yet but I really prefer authentication over IP filter since you do not see if the filter works when you come from an authorized IP.
    I would have preferred an LDAP user backend but a static user list will suffice for me, too.


Log in to reply