diff --git a/states/haproxy/defaults.yaml b/states/haproxy/defaults.yaml index 053b817..eb3ca12 100644 --- a/states/haproxy/defaults.yaml +++ b/states/haproxy/defaults.yaml @@ -11,6 +11,7 @@ haproxy: - libjansson-dev maps: - access + - allowhttp - countries - domains - redirects diff --git a/states/haproxy/templates/haproxy.cfg.j2 b/states/haproxy/templates/haproxy.cfg.j2 index 708d237..f187184 100644 --- a/states/haproxy/templates/haproxy.cfg.j2 +++ b/states/haproxy/templates/haproxy.cfg.j2 @@ -78,6 +78,14 @@ backend admin from {{ haproxy.config.namespace }} # Runtime API stats socket {{ haproxy.config.api.tcpsocket }} level admin stats socket {{ haproxy.config.api.filesocket }} mode 666 level admin + {%- endmacro %} + +{%- macro geoip() %} + # GeoIP + http-request set-var(txn.country) lua.country(req.src) + http-request return status 200 content-type "text/html; charset=utf-8" lf-string "
ip: %[var(req.src)]
country: %[lua.country(req.src)]
city: %[lua.city(req.src)]
" if self_host path_location + acl allowed_country var(txn.country),map_str(/etc/haproxy/maps/countries,OK) OK + http-response deny deny_status 451 content-type text/plain string "Denied" if !allowed_country !internal {%- endmacro %} # Global config @@ -149,19 +157,34 @@ frontend fe_http from {{ haproxy.config.namespace }} ## ACLs acl http ssl_fc,not acl self_host req.hdr(Host) {{ fqdn }} + acl internal src -f {{ haproxy.config.dir }}/maps/access + acl domains req.hdr(Host),map_dom({{ haproxy.config.dir }}/maps/domains) -m found + acl allowhttp req.hdr(Host),map_dom({{ haproxy.config.dir }}/maps/allowhttp) -m found + acl ua req.hdr(User-Agent),map_beg(/etc/haproxy/maps/ua) -m found + acl security_txt path /.well-known/security.txt + acl robots_txt path /robots.txt + acl max_req_rate sc_http_req_rate(0) gt {{ haproxy.config.ddos.maxrequests|default(200) }} acl path_root path / - acl path_host path_dir /host - acl path_date path_dir /date - acl path_srchash path_dir /srchash + acl path_info path /info + acl path_location path /location ## Basic rules http-request set-var(txn.srchash) src,crc32,mod(100) http-request set-var(txn.httpdate) date,http_date() + http-request set-var(req.src) src + http-request set-var(req.host) req.hdr(Host) + http-request set-var(req.accesshash) str(),concat(,req.src,),concat(-,req.host,) - http-request return status 200 content-type text/html lf-string "%H\n" if self_host path_host - http-request return status 200 content-type text/html lf-string "%[var(txn.httpdate)]\n" if self_host path_date - http-request return status 200 content-type text/html lf-string "%[var(txn.srchash)]\n" if self_host path_srchash - http-request redirect scheme https if http + http-request return status 200 content-type text/html lf-string "host: %H\ndate: %[var(txn.httpdate)]\nsrchash: %[var(txn.srchash)]\n" if self_host path_info +{%- if haproxy.config.geoip.enabled %} + # GeoIP + {{ geoip() }} +{%- endif %} + + http-request redirect scheme https if http !allowhttp + use_backend %[req.hdr(Host),lower,map({{ haproxy.config.dir }}/maps/vhosts)] if domains + use_backend %[req.hdr(User-Agent),map_beg({{ haproxy.config.dir }}/maps/ua)] if ua + default_backend {{ ns.default_backend }} # Default HTTPS frontend frontend fe_https from {{ haproxy.config.namespace }} @@ -185,9 +208,7 @@ frontend fe_https from {{ haproxy.config.namespace }} acl max_req_rate sc_http_req_rate(0) gt {{ haproxy.config.ddos.maxrequests|default(200) }} acl self_host req.hdr(Host) {{ fqdn }} acl path_root path / - acl path_host path_dir /host - acl path_date path_dir /date - acl path_srchash path /srchash + acl path_info path /info acl path_location path /location ## Basic rules @@ -212,18 +233,13 @@ frontend fe_https from {{ haproxy.config.namespace }} {%- if haproxy.config.geoip.enabled %} # GeoIP - http-request set-var(txn.country) lua.country(req.src) - http-request return status 200 content-type "text/html; charset=utf-8" lf-string "
ip: %[var(req.src)]
country: %[lua.country(req.src)]
city: %[lua.city(req.src)]
" if self_host path_location - acl allowed_country var(txn.country),map_str(/etc/haproxy/maps/countries,OK) OK - http-response deny deny_status 451 content-type text/plain string "Denied" if !allowed_country !internal + {{ geoip() }} {%- endif %} ## Returns http-request return status 200 content-type text/plain string "User-agent: *\r\nAllow: /" if robots_txt http-request return status 200 content-type text/plain string "Contact: mailto:{{ haproxy.config.syscontact }}" if security_txt - http-request return status 200 content-type text/html lf-string "%H\n" if self_host path_host - http-request return status 200 content-type text/html lf-string "%[var(txn.httpdate)]\n" if self_host path_date - http-request return status 200 content-type text/html lf-string "%[var(txn.srchash)]\n" if self_host path_srchash + http-request return status 200 content-type text/html lf-string "host: %H\ndate: %[var(txn.httpdate)]\nsrchash: %[var(txn.srchash)]\n" if self_host path_info ## Headers http-request set-header X-Proxy-Id "%H" diff --git a/states/haproxy/templates/maps/allowhttp.j2 b/states/haproxy/templates/maps/allowhttp.j2 new file mode 100644 index 0000000..37e7f9e --- /dev/null +++ b/states/haproxy/templates/maps/allowhttp.j2 @@ -0,0 +1,5 @@ +## {{ salt['pillar.get']('salt_managed', default='Salt Managed') }} +{%- from "haproxy/map.jinja" import haproxy with context %} +{%- for name, values in haproxy.config.vhosts.items() %} +{{ name }} {{ 'true' if values.allowhttp|default(false) else 'false' }} +{%- endfor %}