Ограничения для кластера#
Ограничение по User Agent#
В целях информационной безопасности и обеспечения корректной работы современных веб-приложений требуется ограничить доступ клиентов, использующих устаревшие версии браузеров. Такие браузеры не поддерживают актуальные криптографические протоколы и современные стандарты верстки, что делает их уязвимыми и несовместимыми с функционалом системы.
Ниже в разделах примеры настройки отклонения запросов по заголовку User-Agent на уровнях балансировщика HaProxy и Ingress-контроллера.
Для кластера ограничение можно настроить через HaProxy или Ingress.
HaProxy#
Добавить профиль конфигурации HaProxy для проброса в контейнер
~/nscli/workspace/appkit/profile/haproxy/template/haproxy.cfg:
HaProxy.cfg
global
log stdout format short local0
maxconn 40000
stats socket {{work_dir}}/admin.sock mode 660 level admin
stats timeout 30s
user root
group root
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS
ssl-default-bind-options no-sslv3
defaults
log global
mode http
option httplog
option forwardfor
option dontlognull
timeout connect 120s
timeout client 7d
timeout server 7d
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 504 /etc/haproxy/errors/504.http
errorfile 503 {{work_dir}}/503.no_servers.http
{% if state == 'stopped' %}
backend stopped
errorfile 503 {{work_dir}}/503.stopped.http
{% elif state == 'drained' %}
backend drained
errorfile 503 {{work_dir}}/503.drained.http
{% endif %}
frontend haproxynode{% if tls_crt_file %}
bind *:443 ssl crt {{tls_crt_file}} {% else %}
bind *:8080 {% endif %}
mode http {% if state == 'stopped' %}
default_backend stopped {% elif state == 'drained' %}
default_backend drained {% else %}
http-request set-var(txn.path) path
# Блокировка Microsoft Edge
acl ua_edge hdr_sub(User-Agent) -i Edg/ #Поменять "Edg" на свой User Agent
http-request deny status 403 if ua_edge
acl has_x_forwarded_port req.hdr(X-Forwarded-Port) -m found
http-request set-header X-Forwarded-Port %[req.hdr(X-Forwarded-Port)] if has_x_forwarded_port
http-request set-header X-Forwarded-Port %[dst_port] unless has_x_forwarded_port
http-request add-header X-Forwarded-Proto https if { ssl_fc }
option forwardfor
default_backend backendnodes
use_backend debugger_selector if { path_beg /debugger/open }
use_backend debugger if { path_beg /debugger }
acl login_page var(txn.path) -i -m beg /login/login.html
http-response return status 404 errorfile {{work_dir}}/404.shutdown.http if { status 404 } login_page
backend backendnodes
balance leastconn
option httpchk
http-check send meth HEAD uri /
option persist
cookie GS_BALANCER_SERVER_NAME insert indirect preserve
{% for host in hosts %}{% if host.active_regular %}
server {{host.name}} {{host.address}}:8080 check cookie {{host.name}}{% elif host.active_debug %}
server {{host.name}} {{host.address}}:8080 disabled cookie {{host.name}}{% else %}
server {{host.name}} {{host.address}}:8080 check cookie {{host.name}} disabled{% endif %}{% endfor %}
{% if not hosts %}
http-response return status 503 errorfile {{work_dir}}/503.no_servers.http
{% endif %}
backend debugger
option persist
cookie GS_BALANCER_SERVER_NAME insert
{% for host in hosts %}{% if host.active_debug %}
server {{host.name}} {{host.address}}:9020 cookie {{host.name}} disabled{% endif %}{% endfor %}
backend debugger_selector
option persist
cookie GS_BALANCER_SERVER_NAME insert
http-request set-var(txn.query) query,url_dec(1)
{% for host in hosts %}{% if host.active_debug %}
http-request redirect code 303 location %[str,concat("/",txn.query)] set-cookie GS_BALANCER_SERVER_NAME={{host.name}} if { path_beg -i /debugger/open/{{host.name}} }{% endif %}{% endfor %}
{%- endif %}
{% if stat_username %}
listen stats
bind :5000
stats enable
stats uri /
stats hide-version
stats auth {{stat_username}}:{{stat_password}}
{% endif %}
frontend prometheus
bind *:8405
mode http
http-request use-service prometheus-exporter if { path /metrics }
no log
listen health
bind *:6000
mode http
monitor-uri /is_alive
Применить профиль конфигурации:
./appkit.sh prepare_profile --appkit-dir workspace/appkit
./appkit.sh push --namespace gs-ctk --source ./workspace/appkit --destination appkit/v1
./appkit.sh switch_local --config-path ./config.yaml --resgroup gs-cluster-1 --local-appkit ./workspace/appkit --remote-appkit appkit/v1
./appkit.sh start --config-path ./config.yaml --resgroup gs-cluster-1
kubectl apply -f ./config.yaml
Ingress-Nginx#
В ingress-nginx должно быть включено:
allow-snippet-annotations: "true"
EDITOR=nano kubectl edit ingress -n gs-ctk ctk-restapi - отредактировать сщуествующую конфигурацию
или
Применить из файла ingress.yaml:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/configuration-snippet: if ($http_user_agent ~* "Firefox")
{ return 403; }
nginx.ingress.kubernetes.io/server-snippet: if ($http_user_agent ~* "Firefox")
{ return 403; }
creationTimestamp: "2026-06-05T14:49:04Z"
name: ctk-restapi
namespace: gs-ctk
spec:
ingressClassName: nginx
rules:
- http:
paths:
- backend:
service:
name: gs-cluster-1-haproxy-external
port:
number: 8080
path: /
pathType: Prefix
Применить конфигурацию kubectl apply -f ingress.yaml
Ingress-HaProxy#
Создайте или отредактируйте ConfigMap haproxy-ingress в namespace haproxy-ingress:
apiVersion: v1
kind: ConfigMap
metadata:
name: haproxy-ingress
namespace: haproxy-ingress
annotations:
# Защита от перезаписи при helm upgrade
helm.sh/resource-policy: keep
data:
# Правила для фронтенда (HTTP/HTTPS)
config-frontend: |-
# Блокировка браузера Opera (возвращает 403)
http-request deny if { hdr_sub(user-agent) -i Opera }
# Перезапись заголовка Location: убрать :8080 из редиректов
http-response set-header Location "%[res.hdr(Location),regsub(:8080,,i)]"
healthz-port: "10253"
stats-port: "1936"
Применить через kubectl:
kubectl apply -f haproxy-ingress-configmap.yaml