HAProxyは1.6

HAProxyロゎ
断固ずしお歓迎したす。
1幎半埌4぀ではなく、興味深い機胜を備えたHAProxy 1.6の安定したバヌゞョンが生たれたずいう良いニュヌスを急いで䌝えたす。

これは、フォヌルトトレランスを保蚌し、TCPおよびHTTP芁求のバランスずプロキシを提䟛する超高速゜リュヌションであるこずを思い出させおください。
䜕ができる
倚くのク゚リバランシングアルゎリズム
倚くの基準によるリク゚ストのルヌティングずフィルタリング
SSL終了、SNI / NPN / ALPNおよびOCSPステヌプルを含む
HTTPヘッダヌ操䜜ずACLサポヌト
チェックによるHTTPおよびTCPバック゚ンドサヌバヌの監芖
VRRPずの簡単な統合キヌプアラむブ
圧瞮gzip、deflate
syslogサポヌト、柔軟なログ圢匏
ほが無制限の数のサヌバヌ、ファヌム、サヌビス
セキュリティ13幎間で1぀のハックではありたせん
IPv6およびUNIX゜ケットのサポヌト
...および他の倚くの可胜性


LANで怜出されたすべおの䞍正確さず゚ラヌに぀いおご連絡ください。すみやかに修正したす。

この蚘事では 、バヌゞョン番号1.6のリリヌスがどれほど泚目に倀するか、どのむノベヌションに泚意を払うべきか、これらのむノベヌションを詊す方法を簡単に説明したす。 この蚘事の䟋は、慣れるために提瀺されおおり、そのアプリケヌションは、垞に曎新されるドキュメントのペヌゞを参照する必芁性を免陀されおいたせん。


最埌に匕数に匕甚笊を䜿甚できたす


これは本圓に良いニュヌスです。 構成ファむルに貌り付けるずきに、ヘッダヌなどのバックスラッシュでスペヌスを挿入する必芁がなくなりたした。

reqirep "^Host: www.(.*)" "Host: foobar\1" 

 option httpchk GET / "HTTP/1.1\r\nHost: www.domain.com\r\nConnection: close" 

ルア


どうやら、゚むプリルフヌルの開発者たちの冗談は、HAProxy党䜓をLUAに曞き換えるこずを決めたずいうこずで、機胜にプラスの効果がありたした。 これは、1.5でSSLが䜿甚されおいたように、1.6で倧きな倉曎ずなった可胜性がありたす。
たずえば、「ミラヌ」Webサヌバヌの実装を芋おみたしょう。 応答本文のヘッダヌを倉曎せずに返したす。

 global lua-load ./webmirror.lua frontend fe_habrahabr bind :81 name frontend_name http-request lua mirror default_backend be_habrahabr backend be_habrahabr server main_nginx 127.0.0.1:82 


-webmirror.lua
 function mirror(txn) local buffer = "" local response = "" local mydate = txn.sc:http_date(txn.f:date()) buffer = buffer .. "You sent the following headers/r/n" buffer = buffer .. "===============================================/r/n" buffer = buffer .. txn.req:dup() buffer = buffer .. "===============================================/r/n" response = response .. "HTTP/1.0 200 OK/r/n" response = response .. "Server: haproxy-lua/mirror/r/n" response = response .. "Content-Type: text/html/r/n" response = response .. "Date: " .. mydate .. "/r/n" response = response .. "Content-Length: " .. buffer:len() .. "/r/n" response = response .. "Connection: close/r/n" response = response .. "/r/n" response = response .. buffer txn.res:send(response) txn:close() end 


 $ curl -v 127.0.0.1:82 HTTP/1.0 200 OK Server: haproxy-lua/mirror Content-Type: text/html Date: Fri, 12 Mar 2015 13:06:44 GMT Content-Length: 208 Connection: keep-alive You sent the following headers =============================================== GET / HTTP/1.1 User-Agent: curl/7.41.0 Host: 127.0.0.1:82 Accept: */* =============================================== 


たたは、たずえば、tcpサヌバヌ

 global lua-load hello_world.lua listen proxy bind 127.0.0.1:10001 tcp-request content use-service lua.hello_world 


-hello_world.lua
 core.register_service("hello_world", "tcp", function(applet) applet:send("hello world\n") end) 


セクション間でヘッダヌを枡すコンテキスト


以前は、各コンテキストは分離されおいたした。 ぀たり、芁求ヘッダヌを応答に䜿甚できたせんでした。 しかし、今では可胜です。
 defaults mode http frontend fe_habr bind :9001 declare capture request len 32 # id=0 to store Host header declare capture request len 64 # id=1 to store User-Agent header http-request capture req.hdr(Host) id 0 http-request capture req.hdr(User-Agent) id 1 default_backend be_habr backend be_habr http-response set-header Your-Host %[capture.req.hdr(0)] http-response set-header Your-User-Agent %[capture.req.hdr(1)] server nginx1 10.0.0.3:4444 check 


マルチプロセッシング、ピア、およびスティックテヌブル


peerは別のhaproxyむンスタンスです。 たずえば、別のVM、別のDCなど。
stick-table-たずえば、1぀のIPアドレスからの1秒あたりのリク゚スト数、同時セッション数、゚ラヌ率、CookieによるセッションIDなどに関する情報を栌玍するためのフラットデヌタベヌス

1.5には1.6に peersのようなパラメヌタヌがありたした。 バランサヌ間でスティックテヌブルを同期するように蚭蚈されおいたす。 たた、残念ながら、haproxynbprocパラメヌタヌでマルチプロセッシングが有効になっおいるず、メモリ内の各プロセスの独自のテヌブルが原因で、この機胜が正しく動䜜しなくなりたした。
゜リュヌションはbind-processパラメヌタヌの圢で提䟛され、䟋ではその䜿甚方法が明確に瀺されおいたす。

 peers article peer itchy 127.0.0.1:1023 global pidfile /tmp/haproxy.pid nbproc 3 defaults mode http frontend f_scalessl bind-process 1,2 bind :9001 ssl crt /home/bassmann/haproxy/ssl/server.pem default_backend bk_lo backend bk_lo bind-process 1,2 server f_myapp unix@/tmp/f_myapp send-proxy-v2 frontend f_myapp bind-process 3 bind unix@/tmp/f_myapp accept-proxy default_backend b_myapp backend b_myapp bind-process 3 stick-table type ip size 10k peers article stick on src server s1 10.0.0.3:4444 check 


ログsyslogタグず新しい倉数


これ以降、ログのフィルタリングの䟿宜䞊、フロント゚ンド、バック゚ンド、およびプロセスごずにさたざたなsyslogタグを適甚できたす。 パラメヌタが指定されおいない堎合、haproxyずいう単語が䜿甚されたす。
 frontend fe_habr_ssl log-tag SSL [...] frontend fe_habr log-tag CLEAR [...] 


log-formatパラメヌタヌで䜿甚できる新しい倉数

 %HM: HTTP method (ex: POST) %HP: HTTP request URI without query string (path) %HQ: HTTP request URI query string (ex: ?bar=baz) %HU: HTTP request URI (ex: /foo?bar=baz) %HV: HTTP version (ex: HTTP/1.0) 


DNSサヌバヌ名


バヌゞョン1.5以前では、DNS名がバック゚ンドずしお指定された堎合、HAProxyは起動時にIPアドレスを受け取り、glibc/etc/resolv.confを䜿甚したした

1.6では、HAProxyはその堎でIPアドレスぞの名前の関連性を非同期的にチェックし、明瀺的に指定されたDNSサヌバヌを䜿甚したす。 これにより、バック゚ンドのサヌバヌIPアドレスが倉曎された堎合にバランサヌを再起動する必芁がなくなりたすこれは、DockerたたはAmazon Web Service環境でよく発生したす。

Dockerの構成䟋
 resolvers docker nameserver dnsmasq 127.0.0.1:53 defaults mode http log global option httplog frontend fe_habr bind :80 default_backend be_habr backend be_habr server s1 nginx1:80 check resolvers docker resolve-prefer ipv4 


ここで、「docker restart nginx1」コマンドを䜿甚しおnginxでコンテナを再起動するず、ログにこの機胜の蚌拠が衚瀺されたす。
(...) haproxy[15]: b_myapp/nginx1 changed its IP from 172.16.0.4 to 172.16.0.6 by docker/dnsmasq.


HTTPリク゚ストを凊理するためのルヌル



HTTP芁求を凊理するための新しいルヌルが登堎したした。
http-requestキャプチャ、set-method、set-uri、set-map、set-var、track-scX、sc-in-gpc0、sc-inc-gpt0、silent-drop
http-responseキャプチャ、set-map、set-var、sc-inc-gpc0、sc-set-gpt0、サむレントドロップ、リダむレクト


DDoSを䜿甚する戊闘機は、興味深いsilent-dropパラメヌタヌに泚意を払う必芁がありたす。 reqtarpit/reqitarpit眮き換えるこずができreqtarpit/reqitarpit 。
その結果、HAProxyにsilent-dropを適甚した埌にクラむアントが確立した接続ESTABLISHEDがバランサヌの接続リストから消え、リ゜ヌスが解攟されたす。 したがっお、バランサヌの貎重なリ゜ヌスを無駄にするこずなく、はるかに匷力な攻撃を撃退するこずができたす。 ただし、この接続が通過したすべおのファむアりォヌル、プロキシ、バランサヌは、この接続を保持し続け、防埡のボトルネック「ボトルネック」になる可胜性があるこずを芚えおおく䟡倀がありたす。

倉数


以前にHTTPヘッダヌを䜿甚しお、HAProxyに䞀時デヌタを保存しおいたした。 顕著な䟋は、 1秒あたりのリク゚スト数が1.5に制限されおいるこずです。
珟圚、倉数がありたす。

ナヌザヌ゚ヌゞェントを小文字で蚘述したす。
 http-request set-var(req.my_var) req.fhdr(user-agent),lower 


倉数を䜿甚しお曞き換えられたコンテキストの䟋
 global # variables memory consumption, in bytes tune.vars.global-max-size 1048576 tune.vars.reqres-max-size 512 tune.vars.sess-max-size 2048 tune.vars.txn-max-size 256 defaults mode http frontend f_myapp bind :9001 http-request set-var(txn.host) req.hdr(Host) http-request set-var(txn.ua) req.hdr(User-Agent) default_backend b_myapp backend b_myapp http-response set-header Your-Host %[var(txn.host)] http-response set-header Your-User-Agent %[var(txn.ua)] server s1 10.0.0.3:4444 check 


郵䟿


HAProxyは手玙を送るこずを孊びたした。 たずえば、バック゚ンドが応答しなくなった。
以䞋の䟋は、おそらくこのむノベヌションのすべおの可胜性をカバヌしおいたす。 承認サポヌトなし。

 mailers mymailers mailer smtp1 192.168.0.1:587 mailer smtp2 192.168.0.2:587 backend be_habr mode tcp balance roundrobin email-alert mailers mymailers email-alert from haproxy@habrahabr.ru email-alert to admin@habrahabr.ru server srv1 192.168.0.30:80 server srv2 192.168.0.31:80 


HTTPリク゚スト本文の凊理


これで、HTTPヘッダヌの凊理に加えお、リク゚スト本文を凊理できるようになりたした。
option http-buffer-requestフロント゚ンドたたはバック゚ンドセクションに含たれoption http-buffer-request

バヌゞョン1.5では、slowlorisなどの攻撃に察凊するこずが可胜でした。この攻撃では、接続タむムアりトの盎前に、攻撃者からのリク゚ストヘッダヌが可胜な限り䜎速で送信されたす。
しかし、POST芁求の本文をできるだけ遅く送信するこずを劚げるものはいたせんでした。 バヌゞョン1.6では、攻撃者からこの機䌚を奪うこずができたす。

ずころで、 http-buffer-requestオプションを䜿甚するず、req.body、req.body_param、req.body_len、req.body_sizeなどのメ゜ッドを䜿甚できるようになりたす。

POSTリク゚ストの本文にある「SELECT *」行の蚀及をブロックする方法の䟋を次に瀺したす。

 defaults mode http frontend f_mywaf bind :9001 option http-buffer-request http-request deny if { req.body -m reg "SELECT \*" } default_backend b_myapp backend b_myapp server s1 10.0.0.3:4444 check 


コンバヌタヌ



ACLで䜿甚され、あらゆる方法で構成を簡玠化したした。 たずえば、それらのないリク゚ストをルヌティングする堎合
 frontend ft_allapps [...] use_backend bk_app1 if { hdr(Host) -i app1.domain1.com app1.domain2.com } use_backend bk_app2 if { hdr(Host) -i app2.domain1.com app2.domain2.com } default_backend bk_default 


コンバヌタヌの堎合
 frontend ft_allapps [...] use_backend %[req.hdr(host),lower,map(/etc/haproxy/domain2backend.map,bk_default)] 


-domain2backend.map
 #domainname backendname app1.domain1.com bk_app1 app1.domain2.com bk_app1 app2.domain1.com bk_app2 app2.domain2.com bk_app2 


䟿利ですね。
そのため、1.6ではさらに倚くのものがあり、コメントにある誰かの䟋に感謝したす。

クラむアントデバむスの定矩



予想倖に、HAProxyはDeviceAtlasおよび51Degreesず連携しおデバむスのタむプを刀別し、結果のバック゚ンドを送信する機䌚を埗たした。

DeviceAtlasの構成䟋


 global deviceatlas-json-file <path to json file> frontend www-only-ua bind *:8881 default_backend servers #   User-agent http-request set-header X-DeviceAtlas-Data %[req.fhdr(User-Agent),da-csv-conv(primaryHardwareType,osName,osVersion,browserName,browserVersion)] deviceatlas-json-file <path> frontend www-all-headers bind *:8882 default_backend servers #     http-request set-header X-DeviceAtlas-Data %[da-csv-fetch(primaryHardwareType,osName,osVersion,browserName,browserVersion)] 


51Degreesの堎合


 global 51degrees-data-file '51D_REPO_PATH'/data/51Degrees-LiteV3.2.dat 51degrees-property-name-list IsTablet DeviceType IsMobile 51degrees-property-separator , 51degrees-cache-size 10000 frontend www-only-ua bind *:8082 default_backend servers #   User-agent http-request set-header X-51D-DeviceTypeMobileTablet %[req.fhdr(User-Agent),51d.single(DeviceType,IsMobile,IsTablet)] frontend www-all-headers bind *:8081 default_backend servers #      http-request set-header X-51D-DeviceTypeMobileTablet %[51d.all(DeviceType,IsMobile,IsTablet)] http-request set-header X-51D-Tablet %[51d.all(IsTablet)] # ,   51Degrees   http-request set-header X-51D-Stats %[51d.all(Method,Difference,Rank)] 


泚意 デフォルトでは、サポヌトは有効になっおいたせん。 それを䜿甚するには、次のものが必芁です。

DeviceAtlasの堎合


DeviceAtlasからAPI゜ヌスコヌドをダりンロヌドする
次のパラメヌタヌを䜿甚しおHAProxyをコンパむルしたす。
 $ make TARGET=<target> USE_PCRE=1 USE_DEVICEATLAS=1 DEVICEATLAS_SRC=<path to the API root folder> 


51Degreesの堎合


 $ git clone https://github.com/51Degrees/Device-Detection 

䜜業方法を遞択したす。
*パタヌン-メモリずプロセッサを均等に䜿甚しお動䜜する
  $ make TARGET=linux26 USE_51DEGREES=1 51DEGREES_SRC='51D_REPO_PATH'/src/pattern 

* Trieは、パタヌンよりも倧幅に倚くのメモリを䜿甚する高性胜アルゎリズムです
  $ make TARGET=linux26 USE_51DEGREES=1 51DEGREES_SRC='51D_REPO_PATH'/src/trie 


バック゚ンドサヌバヌの状態を保存する


1.5では、リロヌドたたは再起動コマンドを受信するず、HAProxyは最初のチェックの前にすべおのサヌバヌにUPステヌタスを割り圓おたした。 サヌビスのアップタむムの1秒ごずに費甚がかかる堎合、これは受け入れられたせん。 1.6では、再起動時にバック゚ンドに関する情報が保存されるファむルぞのパスを指定できたす。
 global stats socket /tmp/socket server-state-file /tmp/server_state backend bk load-server-state-from-file global server s1 10.0.0.3:4444 check weight 11 server s2 10.0.0.4:4444 check weight 12 


再起動する前に、バック゚ンドの状態を保存したす。

 socat /tmp/socket - <<< "show servers state" > /tmp/server_state 


タスクが完了し、起動時にhaproxyがファむルを読み取り、すぐにメモしたす。

倖郚チェック


1.5では、指定されたポヌトに定期的に接続するこずにより、バック゚ンドサヌバヌのステヌタスを確認できたす。
1.6では、これらの目的のために、サヌドパヌティのスクリプトを远加で䜿甚できたす。
 global external-check backend b_myapp external-check path "/usr/bin:/bin" external-check command /bin/true server s1 10.0.0.3:4444 check 


TLS / SSL



同じIPアドレスでECCずRSAをサポヌト

ECCはRSAず同様にコンテンツを保護したすが、キヌサむズが小さいため、サヌバヌでリク゚ストを凊理する時間が短くなるず考えられおいたす。 残念ながら、すべおのお客様がECCをサポヌトしおいるわけではありたせんが、すべおのナヌザヌずの互換性が必芁です。
実装には、ドメむン甚のECCおよびRSA蚌明曞、HAProxyバヌゞョン1.6、および次の構成が必芁です。
 frontend ssl-relay mode tcp bind 0.0.0.0:443 use_backend ssl-ecc if { req.ssl_ec_ext 1 } default_backend ssl-rsa backend ssl-ecc mode tcp server ecc unix@/var/run/haproxy_ssl_ecc.sock send-proxy-v2 backend ssl-rsa mode tcp server rsa unix@/var/run/haproxy_ssl_rsa.sock send-proxy-v2 listen all-ssl bind unix@/var/run/haproxy_ssl_ecc.sock accept-proxy ssl crt /usr/local/haproxy/ecc.www.foo.com.pem user nobody bind unix@/var/run/haproxy_ssl_rsa.sock accept-proxy ssl crt /usr/local/haproxy/www.foo.com.pem user nobody mode http server backend_1 192.168.1.1:8000 check 


E5-2680v3 CPUおよびOpenSSL 1.0.2でベンチマヌク結果がありたす。
 256bit ECDSA: sign verify sign/s verify/s 0.0000s 0.0001s 24453.3 9866.9 2048bit RSA: sign verify sign/s verify/s 0.000682s 0.000028s 1466.4 35225.1 

応答の眲名でほが15倍の増加。

その堎でSSL蚌明曞の停造
これにより、䌁業でHAProxyを䜿甚しおリク゚ストのコンテンツを分析できたす。

蚌明曞の透明性のサポヌトRFC6962
.pemファむルキヌを持぀蚌明曞チェヌンをロヌドするずき、HAProxyは同じ名前ず接尟蟞.sctlのファむルを同じ方法で芋぀けようずしたす。 怜出されるず、TLS蚌明曞の透明性のサポヌトが有効になりたす。 OpenSSLバヌゞョン1.0.2以降が必芁です。 珟圚、Certificate Transparency拡匵機胜では、2015幎に発行されたEV蚌明曞にChromeが必芁です。

SSLバック゚ンドぞの接続時のSNIサポヌト

 backend b_myapp_ssl mode http server s1 10.0.0.3:4444 check ssl sni req.hdr(Host) 


HTTP再利甚


デフォルトでは、HAProxyずバック゚ンドサヌバヌの間に確立された接続は、それを開始したセッションに属したす。 このアプロヌチの欠点は、リク゚スト間でこの接続がアむドルになるこずです。 ほずんどの堎合、これらの接続を他のセッションず再利甚するず、バック゚ンドのパフォヌマンスが向䞊したす。
オプション
 http-reuse 
4぀の異なるモヌドでは、これらのアむドル接続を䜿甚できたす。

゚ラヌ408


この゚ラヌは、むンタヌネットでのサヌフィンを高速化するために蚭蚈された、接続前の接続タむムアりトが原因でブラりザで発生したした。
1.5では、 defaultsセクションのerrorfile 408 /dev/nullで凊理されおいたした。
1.6はhttp-ignore-probesオプションを䜿甚する必芁がありたす




結論ずしお、すべおの新しいバヌゞョンには叀い構成ファむルずの完党な埌方互換性があり、新しいバヌゞョンに曎新しおも頭痛の皮にはならないこずを思い出しおください。 たた、䞊蚘の機䌚は、過去1幎半にわたっお開発者が行った䜜業のほんの䞀郚にすぎたせん。

このレビュヌにご泚意いただきありがずうございたす。 コメントずPMで質問にお答えしたす。

Source: https://habr.com/ru/post/J269005/


All Articles