7uWM$xdpToEZxqC3+N zbG7l$*7j+6lK4YIE0U&vh@Wu3fkG6~1l_bB51My4S&kXlkP&IU27Y3Tl4)H|`TVXV z?7+@*9-3dBo@Cyy`&OwzML2VG%O}<2uq^n9pRT3GLh-~fTK881Ro5GZa}4Eb_M-6k zX`?I+ZHaV|nD>=H*4qvBcAn2=GhsaF)lXm1O!rFwvZ6e;UeA4KVrrajOLE~PEmYHo z{cS^C`d~3pVm%Pw29aL35px#aZfslG64yjo@>0r(3{hTokelL)i!XF&g2mltw4(%0 zFd+agBq69?pKmvM4_8PIIfn6RF|Xmd{=M?8r6@;v+c1_s|LRz%gR@(MV7Y@tGT~Bp zjz~|RT!0^5WBP4b*C5*DZJ_Lu*;>db@@ZIxF#eJO z{4Bu{N_qK(KUG*Q&V(o&YKeVaiAK26v||qJdm2kw73uKF(ZdlAeZYrEoPiE=u3IXG z{2ZM2e#%RS9O=!BJWO(@zkt|lV#*9|5+aVw1M=E-_?SA_YU%K^#7TnM9~#GRzl2MF zY0WYdFTZRQFZnFtMiz>{J8Vk<6mT#l@^23HmY>{Bgdg+>tWj&5z5gL|z -}C5-5xG6`kAvo^R{O>SAt?b-+?W!sAu&?#d~5Ma%K)=y}8js zaHGc6E`a1Pl(P8xx)U!9ToNr+jR6}15n1FeV2yjRL46LbRI%JH3C4eR_ocrXQMhb1 z5b_|LnjtLjG6Om}bA)J>cCe!>*M;VT?Fj{WPNrXHu~3z$XT{#`+6Il6#urDkXjfgc z=# 0<4kCxZB*Ii>)!hm z=Gwg7yoz6D!o;fWGc_^NFFhfPg7sXL5J*_wre4>|o?kVI9BJk;Nq}HTXSXZov7kqE zhVaJFS#)M(*LZC;u8Cz^* p!XAVdqjW?2h(@1mTDXhRw0VdkV z9($}&hmwpcbt|jDox+PiX?WFr+ =}?whiRwvDM~tR4xH(YR1cZy zkMyznfxtsu^`H2wR-jqcMThxW!buW*AdfbtAtCD 0#=fVz~emCx%%Psk+o zVsDPs>S-7+r{$R<6v&|-uVQV3dNdSnb?*9x9aPfJNsnMZ;H4gWo0y+|R(VSG)^G(1 zD!cEhWJ7D7sL<5jA(^13QkXy|hqc}-c?;Bv)8gmfbgq5+6j{S&6POlo*>AGi4>+T6 zDxBPeUV!?B65eWO%|BCG$i2jo^SIG7VwlpsvJxlU2Gx)#G|m5)(Evsjj9B=Ng2ou^ z>3!_ipCZh+*w_J%%YrSG--&k)lEto?eqVny*33d}eG9Dac3;{y?JO971gc5sF)Sqb zHW~WJqJAA~5WM#St(;gPz4UA~BvJ8>i_24zXaxPc@xx@J@LMWZY9E-%&NjDQKKf#F zt5e0TIhRvdwGQKiumi_aT8#2}%j>m5AKIrkdFfuDg~u*vvhAnMmHfcanB%RrP#yDg zx)Z^l9L*mkkw85}NrtK}kKV$+5XbMU*URVE(3OvHif5``&7^ce52-`G?OH9=J{9R( z`&*ljrPn<$6 oI1&Q(F=)Qyirav=$E;sRAC?0G!)2bc>v3t>)x;}=5^<; zl<~xb=V5OxS|2f3Q(+Z(LwATJZ77X6Xj`EL;H%kh|M)TFL`;NWCQIeW*nx-kxqV)C zMG$i%pCf@+FB DyviV6xrT1f1AkMFb z%UO&LZrg~xg=y$Gb6F4RsP~nk5cBcjbNptjqSY*Vt5j$2>({^;>YlQ$?qQ-=2Jch% z^963QsiM<#f+;mphO7T()UoK3*cIC1i*g}l;$Q&;*G~Mf#YSc8S{93;D+|3kXT0Mg z_Etk^MgHIBm#Ez~vW(mFJJ22_z8G|YX$8x0YsX!cdYzYND2R>94zaDBdwE7iRx&v7 zvduTmwwqeZl{sO4ujN$s`9qas?U(hD%7*Q#2U@-LnbElj<`Nd^FzxlK3sbj1KBwGE zq3pD++{2=@^9yb;SXoR?%LtR-109aX*sTo7k#op{h?j q z1G<@%Aa_v=+a$4oee&(!{60XiO+%-qcN)!|`>p@efVxKwWwD3}nu#$T#(yh3kQ=c& z#plQi 5^D|kjd#bzh<5Azk9p}oK1oEoy?@(- z>ngyNvk%}fau *8jPtqVw(va3>8H2% zbZQBH%6MW!j^87|Opa0QQvkQJBVRXz=d;p!-yw>^$Nv^1Rs?#{Ca-)RH&|lC9sEUP z1TnJLPRv|pd+`>I=@ig5l11cEFv03)9dLHHLiFO@ow9F^KM^ice{SD$Vc;PYFZLgB zd}{jMG*LDX5&lg}l5i?R-EO8A@7_rGc*S7Y-2fO%`?+KDJ`1z(kEPokelfD$)#=rK z?{W61^&OPJ)?nU1*NwcM5mwv!Fi&jqRn8R0q;bFh>gJqa^3p#GZL(zEn_OX }CYRUvXC~zgGa;25AfK%u4oAw0sKl6JRb_poD zZ*) -%zfg s~#lcBQF&G)-L9=4Kmj%iLaf! zUi+O*K?6Fnhtv?KJK@Ig4{f)Qp#?dK@Apu?E@%yN`gr%Y_NCv0mW@tT^U@XB?|GUg z=d?SLD~vk@I$W*NdczpJ9L74OU)l#z#?a<_1TYk9sfEb8sYS}=cixCQSXfH)2|F-B zP`{(nq%r}F@U7h8q|%_b{U5V9{o)nm%+^!2CnWk!ikes*4J!JV9X2NU6Ykk;BuA2q zz(7&mmCz&qHlN0 A zMp^mc1uO140;zvs)$z_UH8`R|%>Q~m?c&P1iyWitq^{Y5xUNDA_foNhnfEC2bwohG z9ee#%07qAty_;=gKR2+WblOZj8^iv nseeyV3*J=KUh#`^WWM zm!VJxSmB=95UJJA?D5ShB>|hqhDHu^cEousITfzfnR5$}^dU(AP5849j9IdL>xXj+ z1<(qC;cVlmIonW;g8tnEnh|QGrW{U+uRHv!_U&U26K!-I*!WR~Fbd@ ek-QDr;?1M6a$u?C$vmHwTX_=0L zCP>nb_jso ?i@;#h_U|1 zmOYK@Qp$d8ZucI)XQn %Dk*!)hy{nfwl%HabTCKm`PKHa0Nzr#PL-p!dtKf{RHZN??Jr r=aB!l&v|62SG0r+jOrGYErFRT33TNu-r zzq*v@95|D`1m2D^tihvsLxDYxo11-CD}c W4#u9d@i6=etWUuWXH!ikewI?D_180j4qRwqNfa|47sH~3y1tH{;8Dcy-r&(Bk1 zE-nd@yPp$^#fs-s2M~!8=63fv_81_($bWP<87A!;8QY0R5uebf@MAN;MssZ);vB%V zils^a(9CuxJmUb;m>FE i0NI;#h=EFM=vReT@V`J)KcgI6n6zWsik&E{D4uF3 zzFRW^5!{Kl$o?w#+T!-{i?tcCi{;JIkrwaOyh>!63ls6G?}cBoH@|(h1V6l>c>wCE zTMs*Wd?r*04g6*jtyFu^1ARiyR@=8mPJU-(-Xff=DhW>*?97Vd2gM+gv`;jx=ikJ6 zCv;p(u2k$g3Clm ?CFcmPFFOH6QuxGwCgsukzP zCocn*7n5hZxHkuO_6dmXFTTxpjSF?2v3WLKYXF;h-W1yeb( F0L9$5zKlD+S$Iusnj5&?+i~oRuN`d3T_x!(7P5LRzFBZ$p zaT2i5-#;|?7?+N5G2~Mx <#xe`)rw&|GUCaQ)_a98 zSJk)&7_!8r?q|;gA8QP=dQgc@-jP*nxyW!|s(BrXaH7FG#l&Y@*yC9Cbg+}qPN+i= zyn(@DL@i6Hs}AL8Mlo9@L}O#mzISPJ)iY&Xa5vrVSNHkt1(fl&B0VLw9m|nmlsw~# zG!d^iKWbpWpOZTLD6PuXR(tk&yxJR*o!ZAY_e>0$QewsbV_|gDGkp^HA2Q2RSxzvY zzVvHlcV7QBvT*eCaS}h>SO?{+*1h=qOamqvH{n~A9^VN#Qq~mxB0u;ww5B*8SYx!$ z%<;+?PZ>4|EDL0}oX6iPgmdyjzKflgg2dmPmO~ulr{tmx``a11qhDZJ*`+1yx0mN- z?iE!R`l3*;8GPa_ICqL)t77rZROpWocZ?wrehXll+TB^}VaH9{+0EB$({>QbErN=r zU!K^=Ck-m*&&{kvxM@o-$Q|%;*Dd_kOwp2^epS8BrxS$A*ttBJPA ujbNWZI@{a{i&6T_9fAPj*P#T^LM5w-wY$B=%*)p{9?D}K}rt7(=3 ?*FLguzq%SQRBa5P;gVu5sX4VTW<{sAJ( Wfc};IQ8PYX&yfDWGUkTI{FSX0DOBI24f;BpsN(+J(lqAtvUafJIbS#Kl73;mQ z*g4|(Vy-RIUp>pyT`*)z)OUwo5XL8O`=!sPf<}?VqX+Q>h8f0t&AQ7Q$CFXjzdV!l z`EaR?3NN1nkEcuTl%I4O^lrLm1{3C5*IE1~k}9y4e;=pDjyG2LI9X=bfhR()03wWr zd+uqk2aUq+)2WdGwblfOgLu4crP!HcWYP`);AHT6!fe!CH{3b1RqZ?+rNHTqzV##( z`)lP=ihNE0-=r IwRSD^Guy&$-9R7qyCQO<-)IyP*A z(Cw$~KF|aR5lx(TA8FV;)jFri!`fAWCR^E(G7xxC{&^WCdNdw+%QK+x7v`Oncq)sX zn#dczfvu$N Ip>MzZjovB-!Zk5ic9NUl#OE~^&We+@gcv0&%$=+ zFbR!>xF2AYS=Et1w4~CGPw2SBsbH_+M*VkeO%in*`%`T7UsCbyt2z34F^e~4Xg1;`6>0J(z5eL| zIb2+|jG _62Vk*`ZxKBY-Qng$^4VUyzB%G7Tbr2#R$>Q(WxxwySE zlA3O4Dj7O+a~UB)_bZzJ6DLD`{zFcVY6(vzc5a9=uT=nR3~e(|*HbN4avKgCIOjPx zTr%aGV-@GtbvDX7v4J*cN(@+5i#j`awrcxG@AHMT@7vy9qsY8WwTSBdnSHZ$Yf5+7 zbzlYZta!2nod>1GU{i#MII^OFccfkK=@Yg5$!Ru|cfc&_&P@3v=ev2x0$&X}>P?@G z>Mkz5A8HqyeGIzz!Bflc0vW-@*4)l9AL^?_*_$eccMgSTz v%=_0uSIdhS}Veit+4hr(>8zvg^FE}5%o3r&@&}%d5&V}f^EsF_0y34imy_jE~ zo!FK|zxql@HJI>p_0e5t&HyyMAvGaVX1X4irOQXb=e(mDZ`+XFH+!_k3YlE0*dbJ& zh(| q;>?$y;_52|r6oY%2mx~yM+ee>5kd2=5ocZ%5N7UP_$ zOU=ufcXIxz!~gQ}iJv83=B35sKtNep+w(|~)*A2%?)~2b-t>P1Z?yXRkAC|*@qZV} zws;LvqgdesPGq(^duT!VD(4NFPnk*rO}Hbh_JUSJ$Qa_SqIrl18RE3Q@tzB~$?3@v zzw5sCvNz0)E_UKg50y&SSy&&!fS<2_)V>qS+*2Knv rGFK3PnIwD>v~$(NGj9W x~wQ_h5m1i>y;e 7lL?5VPCPKWW!;Q|s-ui&7jn*jK1G)Knb8J}8aIBfD?9r|@#Od9S65?t9i5Gd zW`gW|-2vVNP8s(&l_ENBh+o)yl<2~__q%y!exxE(=k{qLyl6d`^dFL`0bvX<(d%$s zqmQEjG^|nfddsE^; m8m}`$O0`H;2=W#_P99C|+>{M?dE?z+r z=uT@Q90P;&IdfmePLi*7NRi}ZnKypwju_-?HcJ;hFVK|Qn5n(1+rNm|nb5SzJoDl5 z5I==-4NRbx%V`NDT9%oeusq@T09sX?nfJAxjk;zPdgDTHAwwgSAgRz!i1CGbBJt1*K>+3as_>cGmHZq7WPaZ4 za(MaQ1$ZZpJV}Yr%DPp{pa_`1S=eA=?OTSd?8n^_9c!ycC)|EMNW`D`BtyT0>6e-9 z`?>k#A*Ark^a`VO94}{!XPE6MEUaYB(MCx>LnJA!FH5--?Ha60_a|ayz(AA7{aNP= zg-`KrKbWlF6ek`6TXD_DGHNuQS%N45P9YK1Xv1DYw&)U}V>wfJ2VcyTZZ!A*V)@Am zl391^;;#dZu*sf~1wWUpq?E*1TxIWu$dC6VHR{n2B_u3LYFEEWShHY#i{;M3<~R4y zw{f>mb|GaXK=|V!m;k8Fu;Hzzf71$bgD6L}i37BG5{+I>SlF*~Hs>#;T`G1eJHjU( z?&{h1?YyWz))W*!Nu2&2NFeVP8lFXQ6or>*Yc*rHxyH}B@Z(!X0`JF+eTnh?KagS$ zA?5!X6a~T0H;*p(?^9n1mkx+ #1S3OM_K@@wpN-Bab+3?fJ#YD-swt zw`iUrw0VlJ`B}+Q*c~TTl1{+WjiSc4AVWVbqmxwIGw$^kOg>1*YJABgR#P5v cv13rEvc~<_Iy``E`E+^yKzU) zj0hf;`q8SIGLe%rsmnjT=#-j&gs?h)8pC-teu{AeYFYfhqdS4i8r@BHzaOa^Z*#jE zO4f5HEu0&?u$(2FGh`9Lx!Y+VP9CK^C*7U8K^f0*y1G=>k_7`wt(U#nu94rd?rF we`XJ^^6o(?gJqhq_8pANhVq_msYg(4M%T zx0lDi+$t>rw>OkCl5M H?YdWu878W}3k6eq@&NXoi5@N>e|mAyW;$l5p HrALq*l%yu9e`+?q2vo-NVbXEH?@J zy$q1Yy8S5bz9l*#p8NXv@{rsi{?OkIg!60v>-Rg54#^Abt-mPlkFRPcLtvEn`9|4L u=APGl{&j(s@-4)lRP}$7vJSTj5cxm#n_fl#SXv8b+MIPfQ+~?#{(l38tgi$B literal 0 HcmV?d00001 diff --git a/docs/document/level-1/fallbacks-with-sni-resources/xray-fallbacks.svg b/docs/document/level-1/fallbacks-with-sni-resources/xray-fallbacks.svg new file mode 100644 index 0000000..df12602 --- /dev/null +++ b/docs/document/level-1/fallbacks-with-sni-resources/xray-fallbacks.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/docs/document/level-1/fallbacks-with-sni.md b/docs/document/level-1/fallbacks-with-sni.md new file mode 100644 index 0000000..1d41070 --- /dev/null +++ b/docs/document/level-1/fallbacks-with-sni.md @@ -0,0 +1,330 @@ +# 通过 SNI 回落功能实现伪装与按域名分流 + +VLESS 是一种很轻的协议,和 Trojan 一样,不对流量进行复杂的加密和混淆,而是大隐隐于市,通过 TLS 协议加密,混杂在其他 HTTPS 流量中,在墙内外穿进穿出。为了更好的伪装以应对主动探测,Fallbacks 回落功能随 VLESS 同时出现。这篇教程将演示如何使用 Xray 中 VLESS 入站协议的回落功能配合 Nginx 或 Caddy 在保证伪装完全的前提下实现按域名分流。 + +## 应用情景 + +由于 XTLS,Xray 需要监听 443 端口,这导致如果之前有网站运行在服务器上,那么此时网站无法运行或需要运行在其他端口上,这显然是不合理的。有以下三种方案可以解决这个问题: + +- Xray 监听其他常用端口(如 22、3389、8443) + + 这个方案是最简单的,但不够完美。 + +- Nginx 或 HAProxy 监听 443 端口,通过 SNI 分流做 L4 反向代理,实现端口复用 + + 这个方案比较复杂,需要对 Nginx 或 HAProxy 的使用有一定了解,此处不作过多解释。 + +- Xray 监听 443 端口,通过 Fallbacks 功能 SNI 分流将网站流量回落到 Nginx 或 Caddy + + 这个方案难度适中,也是此教程接下来想要演示的方案。 + +## SNI 简介 + +服务器名称指示(英语:**S**erver **N**ame **I**ndication,缩写:**SNI**)是 TLS 的一个扩展协议。熟悉反向代理的朋友都知道,如果想要通过域名将流量代理到正确的内容上,需要以下配置: + +```nginx +proxy_set_header Host 主机名; +``` + +这句的作用是将名为 “Host” 的 HTTP Header 设定为某个主机名。为什么要这样做?一般而言,一台服务器对应一个 IP,但却运行多个网站,访问者通过域名查询到 IP 以访问服务器,那么问题来了,如何确定访问者想要访问的是哪一个网站?这需要“基于名称的虚拟主机”。 + +当 Web 服务器收到访问请求后,它会查看请求的主机头,使访问者访问正确的网站。然而当 HTTP 协议被 TLS 协议加密后,这种简单的方法就无法实现了。因为 TLS 握手发生在服务器看到任何 HTTP 头之前,因此,服务器不可能使用 HTTP 主机头中的信息来决定呈现哪个证书,更无法决定访问者的访问目标。 + +SNI 的原理也很简单,它通过让客户端发送主机名作为 TLS 协商的一部分来解决此问题。所以在使用 Nginx 对 HTTPS 协议进行反向代理时,需要在配置中加入 `proxy_ssl_server_name on;`,此时 Nginx 会向被代理的服务器发送 SNI 信息,解决了 HTTPS 协议下虚拟主机失效的问题。另外,使用 SNI 时,即使不指定主机头,也可以正确访问网站。 + +## 思路 + + + +从 443 端口接收到流量后,Xray 会把 TLS 解密后首包长度 < 18、协议版本无效或身份认证失败的流量通过对 name、path、alpn 的匹配转发到 dest 指定的地址。 + +## 添加 DNS 记录 + + + +请按实际情况修改域名和 IP。 + +## 申请 TLS 证书 + +由于要对不同前缀的域名进行分流,但一个通配符证书的作用域仅限于两“.”之间(例如:申请 `*.example.com`,`example.com` 和 `*.*.example.com` 并不能使用该证书),故需申请 [SAN](https://zh.wikipedia.org/wiki/%E4%B8%BB%E9%A2%98%E5%A4%87%E7%94%A8%E5%90%8D%E7%A7%B0) 通配符证书。根据 Let's Encrypt 官网信息[^1],申请通配符证书要求 DNS-01 验证方式,此处演示 NS 记录为 Cloudflare 的域名通过 [acme.sh](https://acme.sh) 申请 Let's Encrypt 的免费 TLS 证书。使用其他域名托管商的申请方法请阅读 [dnsapi · acmesh-official/acme.sh Wiki](https://github.com/acmesh-official/acme.sh/wiki/dnsapi)。 + +首先需要到 [Cloudflare 面板](https://dash.cloudflare.com/profile/api-tokens)创建 API Token。参数如下: + + + +权限部分至关重要,其他部分任意。 + +创建完毕后,你会得到一串神秘字符,请将其妥善保管到安全且不会丢失的地方,因为它不再会显示。这串字符就是即将用到的 `CF_Token`。 + +::: tip 注意 +以下操作需要在 root 用户下进行,使用 sudo 会出现错误。 +::: + +```bash +curl https://get.acme.sh | sh # 安装 acme.sh +export CF_Token="sdfsdfsdfljlbjkljlkjsdfoiwje" # 设定 API Token 变量 +acme.sh --issue -d example.com -d *.example.com --dns dns_cf # 使用 DNS-01 验证方式申请证书 +mkdir /etc/ssl/xray # 新建证书存放目录 +acme.sh --install-cert -d example.com --fullchain-file /etc/ssl/xray/cert.pem --key-file /etc/ssl/xray/privkey.key --reloadcmd "chown nobody:nogroup -R /etc/ssl/xray && systemctl restart xray" # 安装证书到指定目录并设定自动续签生效指令 +``` + +## Xray 配置 + +```json +{ + "log": { + "loglevel": "warning" + }, + "inbounds": [ + { + "port": 443, + "protocol": "vless", + "settings": { + "clients": [ + { + "id": "UUID", + "flow": "xtls-rprx-direct" + } + ], + "decryption": "none", + "fallbacks": [ + { + "name": "example.com", + "path": "/vmessws", + "dest": 5000, + "xver": 1 + }, + { + "dest": 5001, + "xver": 1 + }, + { + "alpn": "h2", + "dest": 5002, + "xver": 1 + }, + { + "name": "blog.example.com", + "dest": 5003, + "xver": 1 + }, + { + "name": "blog.example.com", + "alpn": "h2", + "dest": 5004, + "xver": 1 + } + ] + }, + "streamSettings": { + "network": "tcp", + "security": "xtls", + "xtlsSettings": { + "alpn": [ + "h2", + "http/1.1" + ], + "certificates": [ + { + "certificateFile": "/etc/ssl/xray/cert.pem", + "keyFile": "/etc/ssl/xray/privkey.key" + } + ] + } + } + }, + { + "listen": "127.0.0.1", + "port": 5000, + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "UUID" + } + ] + }, + "streamSettings": { + "network": "ws", + "wsSettings": { + "acceptProxyProtocol": true, + "path": "/vmessws" + } + } + } + ], + "outbounds": [ + { + "protocol": "freedom" + } + ] +} +``` + +以上配置针对于 Nginx,以下是需要注意的一些细节。 + +- 有关 Proxy Protocol + + Proxy Protocol 是 HaProxy 开发的一种旨在解决代理时容易丢失客户端信息问题的协议,常用于链式代理和反向代理。传统的处理方法往往较为复杂且有诸多限制,而 Proxy Protocol 非常简单地在传输数据时附带上原始连接四元组信息的数据包,解决了这个问题。 + + 凡事皆有利弊,Proxy Protocol 也是如此。 + + - 有发送必须有接收,反之亦然 + - 同一端口不能既兼容带 Proxy Protocol 数据的连接又兼容不带数据的连接(如:Nginx 同端口的不同虚拟主机(server),本质是上一条)[^2][^3] + + 在遇到异常时,请考虑配置是否符合上述条件。 + + 此处,我们使用 Proxy Protocol 让被回落到的目标获取到客户端的真实 IP。 + + 另外,当 Xray 的某个入站配置存在 `"acceptProxyProtocol": true` 时,ReadV 将失效。 + +- 有关 HTTP/2 + + 首先,`inbounds.streamSettings.xtlsSettings.alpn` 有顺序,应将 `h2` 放前,`http/1.1` 放后,在优先使用 HTTP/2 的同时保证兼容性;反过来会导致 HTTP/2 在协商时变为 HTTP/1.1,成为无效配置。 + + 在上述配置中,每条回落到 Nginx 的配置都要分成两个。这是因为 h2 是强制 TLS 加密的 HTTP/2 连接,这有益于数据在互联网中传输的安全,但在服务器内部没有必要;而 h2c 是非加密的 HTTP/2 连接,适合该环境。然而,Nginx 不能在同一端口上同时监听 HTTP/1.1 和 h2c,为了解决这个问题,需要在回落中指定 `alpn` 项(是 `fallbacks` 而不是 `xtlsSettings` 里面的),以尝试匹配 TLS ALPN 协商结果。 + + 建议 `alpn` 项只按需用两种填法:[^4] + + - 省略 + - `"h2"` + + 如果使用 Caddy 就大可不必如此繁杂了,因为它**可以**在同一端口上同时监听 HTTP/1.1 和 h2c,配置改动如下: + + ```json + "fallbacks": [ + { + "name": "example.com", + "path": "/vmessws", + "dest": 5000, + "xver": 1 + }, + { + "dest": 5001, + "xver": 1 + }, + { + "name": "blog.example.com", + "dest": 5002, + "xver": 1 + } + ] + ``` + +## Nginx 配置 + +Nginx 将通过官方源进行安装。 + +```bash +sudo apt install curl gnupg2 ca-certificates lsb-release +echo "deb [arch=amd64] http://nginx.org/packages/ubuntu `lsb_release -cs` nginx" \ + | sudo tee /etc/apt/sources.list.d/nginx.list +curl -fsSL https://nginx.org/keys/nginx_signing.key | sudo apt-key add - +sudo apt update +sudo apt install nginx +``` +删除 `/etc/nginx/conf.d/default.conf` 并创建 `/etc/nginx/conf.d/fallbacks.conf`,内容如下: + +```nginx +set_real_ip_from 127.0.0.1; +real_ip_header proxy_protocol; + +server { + listen 127.0.0.1:5001 proxy_protocol default_server; + listen 127.0.0.1:5002 proxy_protocol default_server http2; + + location / { + root /srv/http/default; + } +} + +server { + listen 127.0.0.1:5003 proxy_protocol; + listen 127.0.0.1:5004 proxy_protocol http2; + + server_name blog.example.com; + + location / { + root /srv/http/blog.example.com; + } +} + +server { + listen 80; + return 301 https://$host$request_uri; +} +``` + +## Caddy 配置 + +安装 Caddy 请参阅 [Install — Caddy Documentation](https://caddyserver.com/docs/install)。 + +为了使 Caddy 能获取到访问者的真实 IP,需要编译带有 Proxy Protocol 模块的 Caddy。建议直接在 Caddy 官网上在线编译。 + +```bash +sudo curl -o /usr/bin/caddy "https://caddyserver.com/api/download?os=linux&arch=amd64&p=github.com%2Fmastercactapus%2Fcaddy2-proxyprotocol&idempotency=79074247675458" +sudo chmod +x /usr/bin/caddy +``` + +直接替换即可。 + +::: tip +建议先通过官网文档安装 Caddy,再替换二进制文件。这样做无需手动设定进程守护。 +::: + +编辑 `/etc/caddy/Caddyfile`: + +```Caddyfile +{ + servers 127.0.0.1:5001 { + listener_wrappers { + proxy_protocol + } + protocol { + allow_h2c + } + } + servers 127.0.0.1:5002 { + listener_wrappers { + proxy_protocol + } + protocol { + allow_h2c + } + } +} + +:5001 { + root * /srv/http/default + file_server + log + bind 127.0.0.1 +} + +http://blog.example.com:5002 { + root * /srv/http/blog.example.com + file_server + log + bind 127.0.0.1 +} + +:80 { + redir https://{host}{uri} permanent +} +``` + +## 参考 + +1. [服务器名称指示 - 维基百科,自由的百科全书](https://zh.wikipedia.org/wiki/%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%90%8D%E7%A7%B0%E6%8C%87%E7%A4%BA) +2. [Home · acmesh-official/acme.sh Wiki](https://github.com/acmesh-official/acme.sh/wiki) +3. [HTTP/2 - 维基百科,自由的百科全书](https://zh.wikipedia.org/wiki/HTTP/2) + +## 引用 + +[^1]: [常见问题 - Let's Encrypt - 免费的SSL/TLS证书](https://letsencrypt.org/zh-cn/docs/faq/) + +[^2]: [Proxy Protocol - HAProxy Technologies](https://www.haproxy.com/blog/haproxy/proxy-protocol/) + +[^3]: [proxy protocol介绍及nginx配置 - 简书](https://www.jianshu.com/p/cc8d592582c9) + +[^4]: [v2fly-github-io/vless.md at master · rprx/v2fly-github-io](https://github.com/rprx/v2fly-github-io/blob/master/docs/config/protocols/vless.md) diff --git a/docs/document/level-1/routing-lv1-img01-trio.png b/docs/document/level-1/routing-lv1-img01-trio.png new file mode 100644 index 0000000000000000000000000000000000000000..3f3e27ae8f3b19d5b78adf3143e06191bbb36fe9 GIT binary patch literal 1326500 zcmV(#K;*xPP) Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D|D{PpK~#8N%>CK2 zWy`jv2d#)15&I-BCnb_lk(`uLsS2KoJ8m${xZ)OWWQJje!PB6#R}_5T|2OyUeT*?< z#oA{dBmd~rd-GO%*^4pej1T|M|KtDtx8HvI5S+xvj~`pzOaNW{`0-;C#fR^5AijV9 zUe1 Fva&eK-fzf3Pv9uiqhlECHI|54z>Y#4J;j02)n+&_6z={E(o_1FpaR z_Tl?)KR5vTY1@Zyr1{|k)Hj<8e(UL*!tZqp)RmDFN< N`G`(ya1*{EjV37=6}tz1{ad&!7zhYt^NL?BY2@or}A!;$V}c?4Id!C%1k6E z%I`nEhS_ XFH>W82fHZ}*XcL$(=(DZ8P$Uv=iBA3A5wX;|gr zV>D4~sx3j=djh>5zd311gc8k pRjHt`L& mHLG+Ozf%(ujWux#dQ#HE8? z^5GE1?pwDa5#I1T-@2~XUV07L&42o>=(tphH;H5Zu$M}t=jaCaeHKhaXVad6wAYkg zO^T64$|y*1Cqmp~&i|I{!c+#1*q0BVhob!6JO!6BN}}jD+hV&5K);c7P>xo|H3fc? zEU}ph!Xj2&7fsID`i(VTE(_i6Asa}HkV(x z@TX02G?nC^3%8@1aZy$_cYpy*fKGvEIhmHS1ygK3%~YRje1-rfw{+aieWQ=K`S}9< z_T%lNH+X;f^5q}?^7i>Nw|pPoxOMV=&s0J3S2K{Y`h@hjAKTl-5R4$ n7v1h%MNQL(_?_iM3n~uN``x*6AA^V^oQ?Xv-Fs{9ivKdP5F^FC2qYzbQO@s zM;-y*zA%5JoF#M~z1M}I{KH4@vG gyA38Zxbs!!&63IFSNhpPJZ-gb4iv|XHb**-)KviXxS zW$#!%(#Ve=Kfl?x(CTmt?n3(qN@%9yU;gqJq V8E3gJ THEy@w}x)na`-GIwv};EJBuI>FSsHfGyp4*~7RU>Q%&I#Qy={*C)w;P?&yv)sw%{ zq71bdF9)iyi4!lGCmt03Q2##!{K*OMxCG7~`$bg$89x#I2aA_EKQL|czW~PjuVL#y z7`Cdrcdn1cGv`lX``p9>o+shv{Bt&_UySt 3tJ5KLG4&W0eQ`6lai89N{{QlsCxJX) zyutCopmY?XH}~yvFb#YlE+p=jmIpRxqn;lCAGP=}`D$)d)GOmgl>yRyBXsgXZ8vrm z(Iz$xCYvCU2Z*Y ekeUoZMrqS&jfI>q@$^#RqaNl|{4w^a#n(x8ofW j0g;`Px8p2IClx z6Ta NR%g63?hw(Q3 KKZc&-V$zi1d z#<(xlN*Bxns#~*GVEcTCTbRuge|y-(-vx~Y=+Yj{qQBwL7AH8uCq2Gs%PQ<@6g-yU zE`Q}XlWde83@V4;&G`21_itanGQte+;dTdNZ9zPsy$YsY_$`CS=fDGP#~-5!oY*t} zC6+W(H+U}+-I*S};YCCKJeu>b9r-%OFW|I#g=z0|i++OkzytQWt`0cq6VLo`%%r0C z3} 6sjdPe0$@w43)$(+|TC9h?~{nKv*Tu8RYmfwcW4 z9(1f6ZmF9}q$;e>Sc*!)IYl@9Ja6BhEf< `^|Me~6CAubB8TqR)3c!<2CwRxhNPelPcmHCG>T%RiXP>b)HT zAZrx?N$eR|{E0Td!Yz~c=j0h>n{bcdZNe+0XY@tFKK$i-tKr>H eWmW-ngTN5CZq(~3rSoLyh3H <%@S%GHg=fiJ)H%FV!x;H~q zTK#f5MoH%pm~Nu@3B9T>_Me}iI&&pm2y=FrmvHjjALvH#$|{+CJN>UzhiEyDewuTo zRRa&qR>4Vwhj1IMl2$+TFB7D;_K?H28%wLiC}kc&YPV!I^MtC0axpY>CvOtF#F!*4 zJ6iyg=K*i)nX4FX=2**ZRfWdgI60+vd%?3lQoRIJAIgF)U`K@C6~_YH<%u1xwwtE3 z^VhXt@@GM Tur=-kHW$ZhvS`($_N)+te)!KXK0TVzl^eew0~=f8X@(M=D2 z%ZD+-k3M^Yx*+Gw=YRN5|J|+>n|{zPF`ka;xC!Z=j=_7tcK9BUotj1I$e)leH4xA8 zvbYi}koJpwnnaV5YL(dj#x|YCS)H8RlNjvk#4XPd4ET)t5hx-n4EzadNO1w((rUu! zp4qj7_6r&*iVh^(HUFSLF>UgNPnofn?!2te1rrLO8xfRvC=10VVD6l@htt&q45PRT zda!1>38>>MLhWL0M9G6Ot4p0FDjw*rys6*Nw5PqhQO&Km8(um85v~p?(q};8z6DI^ z&}``qeI)>&m?6huI7K)N!6Pp76Dy-f=}L5+PwI|yy}YmWh<3&95Qt4bVofAU7EM@Y zTlHo0j_n`ux98S(HMI@GF`wz=sUH}-lqYT+{oj4Ix|uA$A@2MJd|-y{b>T9X*wP36 z&g2)V{|xs*#lsQ(3?;fBUCh~k#9cA`fNZi|DQ|fX7~D8#{xQs8KY|)RSr#Jn6>eu(V$J7ARH=?mckc5~Owq}ZJ+nE~!vqVS z8ohCMC7wAN>$bmV!Sm-d Y{#%?UsHkaoo6v z( ^ zDp=*XEVNo*kPe2x1NV$*aXo^yZ;a5KaS7cEZt0?%8N@@mq0(J?A}U3ty;5KNs==F+ ztOyRQ#)*@z&Hi !Ri?FarVNZAoJET_lbmw(ynEL$8G%KQ`V-1m z=Yt=@rPi3a!F%)0-CKDcw7z`#l$-mHaJZL;`0TH!K$CxQ%Qj^ !rNmlIDX)=gSz>Y8d!o$At3BPKi579N zcLR(e2*7NMptiBf>sw&6>L}2^z3|4ALzgP;)TnmaLrb>LL3u@b;HuNs_DOK+3$n4E z4ye; 9C9u1v7-_Xy@Ul&(4 >pa#ix$>WifXK0pIFzvNgt%SYy@dE+xn%<>;7N zOw{;eG-7kWu$+{efSS!ZsQRGw;RerBjt(rb`N73$Cl{kK?VElUY1qbgxO8fE;-(*< zgN4_dv&2KT5s@qVyge-ekSCn!70cVkL3bo3_;U`ASY7g{xjbH;=@O5q4xQtU$NGCf zk49|_a}hUWXZ7st?$y+6tGf(d8H&j_$Dz|+(zA5S9I2{t8q&;^8d9Q`3G30B8;b+w zZrH-4TLP5coV2TR?^bqo?dl@%ZmP-0P!j8g29&S1M{|kFFJtzR?IUi=$=tdf?VLmj ze*DG;QgZV)P}Ng<*^XWx%$~6NXqgZ}R*mwt5P)g;i@c=wa3G>Fdb5W|TmB7?(eCI- zZKNuvnJh$yhKVqO&?|1j?zAP^bx+vb`r01XnBSOSiE}>6vttkP0r=!N<>h$Ti`Rg7 ze<(4(2mH >W~AdRXiOcbYw55Bml_ksB)X22ibZs=z`wYM@W zy?mVG%GC#LxRAZL6sG3kYl!wy+L&Hj2Yw}1C-x}x5b0`Td=Bb=E@biJG_FATJJ{0Q zb`f3$3CA%mEo+hv3YV<75zvLTjDmvIvgt8%w^KOgwgFnE8 k!{IUZ{=ZUNSx4A^< zR(hZ6a?CR)n0XSqfp4=b=tyl43hW9By^{ghio75=G2%Pm*FSv)wfqI^ P zxF~AaQ>vn~k{_67#yBxb#-i4S;F&6V9&rvFEQZgo9yLKHP9*J`7^j;WC0;KmT`4`3 zC5q;mwpeaJM(&BKQ$0E)DmRn3>T6f2{?NdVN+0b0RMj?;DE?wy=S~8&dWh9b*Eqei zcx#v(B1Ls+jQD9j_&7L?G80LsT)HDV(cFN3!?7B*@sm=ij^ZX=F9ph8KpE+nY+^cY zs$fpxl;5(OhW(VOmcl>T(C4YXIz%D!alU8(p>6o-b2k}Eq!|NZn_eS_Um+*QOM}#h zyEqQjs&
PNH%$!bA?vs??zWNT&H{4!B8(#iU zLtnFNY=fy3Noya*ID~jNTE@=SC8cgw0QYvOJ3tc7VpQXB0pq**(Ki3S2E%%l4jEia zY~3p2cp9(}CnhodI8~7(mPWDZDBS2`dx0qZzyYoP9QFJXqw$W;Peeb#gGpUb_`QsD zpUj!c19euT{N ~IBD$0lI?`Le^WZ}>NISa~p2$ZTRV zI(@w64(j0n4gFl6L~ZM&DF094Csq$Wf1(MV(|Z8?2c6A1t0z=Fq`UeOm7W;EJ9uav zDCc2HfDtb|SdG#XM*RP8v{4Tj*?)-ON`D*i^yQ8C34Xn4r>oMN^FX}h7rR=bsOV3j zRy7AF{S&Z_%&Xidbd&*9H%aNg6+6R?@}Du{U~@{mhv&qaZLv8eHgNmQe2L`pnEwN+ zSqv*^b(hb?F8{^QKZ@4!XLwfVJ_ewX7U|UKx2l!c<==p97{c{?K+%r4qi+uAooGR| z MM*!bar!wwNU29Gw1Ju?Y6|PM|sw4Lmry5iTAL(?zBqZ`|V)v>HPY}hF{sp$DX-0 z1+{uWe27*_smM39X0?Xl-C=c#GK*myE!t4LoKS6`#q)0gg7dSSVk;NkUF+=TAG%eh z<*honc9=TZMA3e0SMh)fr^+Y41ZDNh1m#p;Uk55Wflf2o`4ne*ElWJ3q6eI!(%|Gj z5MZYP+R5$hUk4_5z~}ChI2LCh=;EYLlz*1b{Z=4-K++c{U7QMiyeg+j^lUYuBo-d3 z;M7<93DJ6i2CYsT^_Ii;Be^wVW$hcJs`>PIcWCMXbVX5oHz=rn$0)x8G9Qta{}S5} zzx7{`b|?8pnMHL#&B1ncGQmUjC6b8dE#p}9x6gLCtqC#{ZRQEui4GSjlv{QsQ__}} zefgAK@v(IqxWdng^56ca|INQIwOIv|iF#kp+>T(oGe=5N w71U=2iak z_lT${yfp796ZARXR0)?0d20Da6Lb!nvG`N+6MBf0^R7;A68^34HQaGKER??gO{2>B z_S<*A1oXoLMJA{Jp-OHl`q6HZ;_jJq?liQux(+3uGE{i8lluCQGR(IRevhN0>RbIe zkRqa0apmT2l@XiQem#i(KsPIsnA{*}7KC}I5MGHt0_lkvLrsREH<^~}9bqK42&!+C z_I!ZTgJq#~G0kt&dFj^}{UE0zhAAT@VRxvb=$vo8!f*3U?+*tr&Kz(SvjcV>IJe8z ztiV4%ChxarZvLa3Pdrp4k~2oav9>D~!UW+s94~O{7j)uE^A39~|Nac@zF)(i@SC@V zp6!;l%WT_}?I-W0pO0&XI1207?b@Ets;)U-M>}Uacz1is5WXS2pu)j9L##1+g2J2+ zWq>2Fs~0gnaPo%+Cw~QGWL&eqez;aFzjv{7Bna-JaFnyEP%v0}x|->GMd2VGCVhkE zs=hdu)p49i>vVmMBcQP_;j$*4DQ#a54yVVi(V?0(SpEZGn!ch_D(y!+DufZ#acQta z3}KKLD7VokhYVjG!x`qn^n+PnN)$r}H-i@-ChCvJH7HlA M6+KgX{;sE%@~ zFds5cHM_coDU0x%)$IArq5Qe@ygYg_YMH|t9eAZAlsd@ECuJ1m5Kpt1<`gv#?-Wii zl{&xSb}dMFI6u7@RcBy~z>Aml{HQ MW!f8#<~f{}Ac$g<2S*nc|{JCLBNd zl%IS5boJ=ZPpuSGxQ-D!Zv4ZMNyZ;sPfVa*SRpFvtg>5jXXq0+%5#@EM|HxCw1#%U z_?*(uoVVvh$x$?iNXr<&FLt%1nn$%b>4H0`vM6Jaep?*N!Q@gNKl}21K;<$=uoP<3 z8A4+8`Y<;f2$6d_e_!MC=P!P1<5Pag{IkD*&Mh9}rS$VBry@D5Tc&+u)7d$3R|)dn z60td}96nGKK$FO3HnA-#`m6<~&nNw(V?8FH-hCy#nI5z;H>rS$K=IqB5B;Q$`&1uN zyj#s(Yi?vS2XJGQ_Vxqd iK%Vp0yX6geF%%BR_{seuwfKn;wAmEh z$WjA|yE;UlPKIH^PC3%jqFy5%vY5*32HC e zC9w|^RUv+2CIc(GkoDPba7eq `l5 Ka!IBDQxRVE=GIveSAj^QMK;B<4g_(vrn+Nd_H3PmQE zQ*0wDgNN#Y@7DkvXsStHNc)G?T&pa~&s-KA{71y}v6&k?hxd~K%)+dgzbl#&We00l zclkHqxfL(l_0z@*6n-5Y *>!{OaF5^`4QLk=t|@Czv;gr z=#N(xyA>zu9R1VeAtGi-xvw~{pnrHZ{gt#|rc~7Y*$JH9-kk6@cVSp}RFsh%v|9dF zs4{5vCwSH==T~h1F8Fz%Kb6KqZ#)23&v@XURqy@tP*lRFf`uw{_~QEoP}n7KsDg*; zd#KLVjM2@i)$=AND#I+FvP^)&WS_R|=IlS;c*2LM;Jjfj>iGd>)`UPiR*8lKcqUv? zwOUne>qjEW1XF*71}%0D;6e0&Ej`tA_fxC)U>5`@y|Krl)%Q?W8!wY76O=9!JaabG zKCqc3iihaW$!t`##qOoc)82UN{2|0kJnL-RjkDUB0H sCSy$LReasJv^@7&Ivpko?R^#IUEuUo z%OVyRcuL>QPMXW_!nUdAB(U(TKflZr{r&+beufAjZ~{vA^;DOQ%sg_hQk}2)14R9u z6ld9dk3*t=8`>{%#6NnnS0Ir6+W&R9%$99wUO-KBvtbBr+V{`CWAeWXb{OfQA3r{2 zM17snZ*8m@<4f>-B`>+_BxeEr`J?|&@>G3Uc1Z!EN_Y8C-K8CR*C}0xn?tpnPai+i z33gbPYnbCfdVb$8`m{b1wQppl;-P4DdALa>_Vy;?Wl7C)vg%lzn#JuVa~s-CAo|P0 zt$`(ej_RAiL2M9$5pU;g$k+e$%maRW`~LDBQ(oylVKiUpJL3*CDCmqW+Qumvot3|` z_t8AIT8Wod{f`VP_>n)My;7BjA5Ji@H}t=ROZk@nQJ!#7TDEqepHkd=iKY56{qV}q z<>HKG8`meycfMtD^0{=C-ptN~RyPuk+}d5&kb!ER`Migp>r{H`v@g0Wis!|2O5elI zFwU<({**0t_TkO^Mbxk}>cmg-QU4xA2ea;uanDTXC7@m1{PQt 0*Ab>FBNVdFTRT_?u^KA*h?V*7sbfM+8fQJeFc%LQcWz| z&ky+k=7Zwrd6l;8W^Cx$A?*b*Gv~W;m;Rg5-~2;>#moP+1ysMefnNB)<`~Fg(EO)2 zj-+UB6`;pMZ;QE(z+q={PZJMKsSZW0ev3XxMX0cn*@$ji`iLsf?X>0Nhfk@sjUy_e zncQN+{Z!Zkm|cn8CwC4z6K;n})SPm!6zFGQ$m1?n5VY3Ra;x?I$5(B7zj0iE=p{Mz zpD#C{+2}0=vn&&=bIdR?fzEaz2vRAiv K`cm zf=s>yfeCk^G=Y1+uS~Vv>0$fz>(_cg+ xwX;1~{aK3AC@uN?3==SmfhP`d(2A7g5<&}*y z-`Z^_3_abQ>}aWpEe>5o+UUT7pbGozUnTsk63w&@f&}_e!fy!Hd^Mv3&2s~J%0Zi^ zAl828QSPCT-6 4&WAq zG|ui)G74%PR+`XTH0zh*;-KHQu|R)A^K1AVk~VmVKynbEnr z9N@?4l>w4Yb87gBCscRi?EiUa?Q*3%)03I-?NWdB#7@RFsi(h%hT#L9FF?1->UsO{ z37V{SS^U#K{jS0j-u`$0`G2
pCfI1ULc6;o-(l=xW2-H)^j&r3Q!P!;&c=E)T*Bx#Fkt=S96_v>8$h!f z5KMLHWc%_@ic (kj|z zQO$jXttEif!{;b0oXk~9fOx(oP-F<2`J-s@FO2ypdfE;lO4H18eu6#j?}Fy4a;Y6A z6Y&YR4dudYP ROvce2?IZxMULwXO$e$;onIn9I-B4AJvVKTzbBlTLf3@H6~E4?Lm)ZegBc z{yYhSHqRs5%i`xPID6(@+-8*csrDn{ycVaOG@DA2FQ=Nsa;vBMsxx1AFV~0?M?>UL zIhzJu)J<)k%i^igw|sPRNA>Ugvd+Cl&UT|ie^H6k+%&*E+p_ziqB2D*2g-A+Pc7wz zXZ;6k|G{;wPH7I~|BO6qHvA*WQ +dNHh7VBzo2SJ84#~ zy>uRRo?z%(O9v-&Qz$1A@#Njwux{~NUWgy=F%du_duVxdEP&M&cge&-4wQyj;zSjI zcL*yQ)raeKXk%^WDFw~r)(;20e2S?)4(Wv|kWa7Xc#-RUR%@#RyepX;dYWp-E@e5I zOWm%O!(0PO+3HDy=pGLYNsI>z{~w1>xoc;#%=Z!Wj{#Obi|4%zC7V&(D(!m%M<1eT zLa<`F7C|%$e2F~xeaj=zMs+APTGhpwRscA RY~-&m3!cp#f=tp54g0Y2~-I8p>=aI)V~G38hk@SGApqpEf8g3!13qVcW8Z z?-_Jxf1c2OuFWcwRc)5Ha3m6K0+m2O52#tryg~BCUlk}PaH@T 0wUy6ip ze>n=2uq31@QytYcjb) ~|^y=xytvkMbk zy2H(V2XnyWGes<~NyRi_HuMDt^q03!opCZhz8NhIs^O*q`PkrWbyU+hDfmMN57kFx z qH6V$w$piI5*?U5I#o?S zPOhVK;prfo5G&}4Uiz&1*2=#>kO;=L>JiV)>Lku1m<~UCp1BkL -gir>u9+E^ z)BmG6N>AR1^XstpnG~1X-5cXR*vySn*>$|=bB4f62?yd=4<}~Q!eb97?W-em+(pn* z!nVJw?;?0#x{oKHs|8llpvPuTHNm4SuGO)(*7oxwYV~wboUj`PB~H2Ya_zawDM)Q3 zkHpJlV!vZSg!W+eZf1!=*p)q(#Tm+kRwm08BSQ((&jAw%m51%6C?RJ%kqWIv82*%# z5EG?);xN2MaVS}Sf~#qZ@;n|2KNrR17mxZ0kzkh2MEF&x+_E|QnAE;T)%m)xF2fvN zlNU0vU~2IIq!aOgQI~&gA-ZF5`Qe;t56iOqS1f)8(oP~1rPZM)2g^i^<2?@kDBd@7 z*cRwIKHOBOj)FG*=Vy<-l3|(F*H8Q-nQ#&BW)2c9r=aw8oC>+W8S{r;P}#U}qTo>? z7jn@iwA^TQLIiE~9!xkT$}iG4QCs3P5jxI?Gq#p Cgjo)>I~C6PkJ+rjpC(A z*^HY_^XI-1j?84mt)A=1p>kBHw%_{kI)}_GHrvnhVUT;$%#(Ie@4oFmFOYt6+s9Y$ zWaqK}_rL!2YrfGyStNpY?vx?KGKx){w=4lzU$%|hbC|z}Z)!^WDO_j?iZ3~R&f^b9 zhoU_~`swVsflDCT-*BM)Sxnz14LfL(3Xyj-HX)xX4^}HsnUS#9KYZtrN-~|FF|xXP zGV5Z7rZFH+AS!6 2$W(TiuPg=C@E2F;xDY-RF^U`@Kz9taX5wHlJ1Z3;6@bzkka zpAo7KmPv-i|4ef$c&yRU)B-YB=2@7~qr!vlrH= zm5%4ReC&M;S>55R7gK1fMw _o B7;XJKp18Sj~J9 zPGm1BxrtX$^lO^$McTN_-GzXA%M%`1JF49mlrHmG|Aouof#2r5Zq%*kJ1sBHd;SM6 zM~x2G?q+&4;l+qn_A0wdZmxhEUWwD~VSn#8(z!m-Iz`*yLAr4$Q`|%gRd_V~13c;e zim@4hB>kR#r`jKS!_6)wZl}3kNIefpbVl(U$;B$R=bz)H5<$Iaic>D#oxB;!vV_)T zr@9HiUBgfh*bTq@q#FOv$uqn?f%b55(x=UtLvgxf1gl`uLHP@ X3hry{A4&2w z)tx-ZWr(|mGE&0lhUj#0=np-d3%!4Qf)=lE^qUJ!f=!Qd!p7?CtZAAY?u|AoDpqc> zn`wQv;zI4VxnJ!pnY)fgnLRi 6TM#?y!Kpl6zcyWNimMa5b-v*^$JZq^0Cbb z=GHEsm_d237x+JOIEeKlB&6pWEj{fTT>N0uC$refOLScKr^`;9eIng{I8hE|QDzbU z7g~Sj1DI_)fX0i=Nz9HKzwzNY;)GM;&2<=Cs d#LHyk6cuZdFseVe7l)HP zb63G_W?pf;eex^zB+}2=`b}~k=9gtgJk5w)yS%Ru+>Cmg8h-!VNU9Z;=)EpwtLg=K zt4O~A^l*~-M*9|g{`{G;x2_~fS$;mAQ$SIZdO*R`Vip9NE_niGo{~~qZB<;qN;AKx z(i`~RpC3(VT>2-G(%Z+NFp%M2W6e3`)y8L30ZbiE@|>%Q13L*cZkDTalK7^8eirP6 ziso%S&VIWP3vJu9s1YE|HqiLU>RT9Q%G8VO_MT1P9tFKgzh%rrw^ #%7iL*GQ;mxAbsXzGn11(bed+ic4ii+ z7_@1bkTnSTlNxzKs}UmCvbMB2jN0U#swx}tD0oh+!UJG#ofF;j!D+P;oE?^#A>)|; z-2v7%Cy*T;B&gc2r{vlz{JK>%T1x-5xHW5D{HEwp|Zv|D5>qZd7UIzVKA173gNN zN)S6?i_$F=r614~iqpw_g9A$?L9?;XF8?~E!?MFUyd0ZGc5RMJI^6(WKRL>2?wxke zh{}bNvlTWWZ7^A9sWfz=FV#ZMkVuoVZDAgunW-^fNa?PT*G}rliLx)moP^iJX@rTh zCig~L8Xv3e9RSWBysnk$Vhex0;BaPH27RGu1#hbnsfOA}hJ~*amwc;~_*t1o)$zuz zrr90&VZMC9QIRFBUz)RVkEg{ `E9n z%u)y-9*$E#sivXzyS>dx`PrZO3nq3^?iFlqM@-LCzkp9~edx4zqTk?nYfaf?R@_<~ zc6b59PzQZYGGtyCF53&a9=^b%-h#=lJ^>8@YEY}^vdAoX1z)bIsv|E-kl)mv&CA2c zBHc^Pqr|SF(aa{HxI~a2O6qWPg5v~^pna0(vW93W;-;k9UIRCtda_tf9x<+W7wq4% zIsALJ)sG$s3~#QW2VA$7f^_Vxr1j#!ZDRKj2_mhr6{l}%3VNH!da9c9bL?IsDLkfq z;Sg1`jCKY^&fX!KRr|>M3U4r`)e#r&3u&}k-dwb1ig@f*l~ZySqZx#8 bg3%-*9 #@I~Akc5Ap&YBlW|k<(q?{@^bEeydFw1#voEIGBlu&=> z;zEW)QMzRVHCWkSUZKg@*8E&Z?Q6cik;dpDJ=VNqATkV|8%*pDR2tC5*d9upqAGUN zHZy8BWEhsaaVm&znMDYkLgn{5l4QrIbdrtk1xyG!(*~qT9Y92*1S|X=8}dy~#W1pO zjj!@)dM+q%&wO$&jh5ZjD1kvjhj$R^Jt|Z0h67MoDR35R9hC_|)ln%ki|&M}DUx== zEY#i*F>48C0}MUmm!&n&S$SjFPyFo |JhdZCt^a>%lTSw1 zte{TS)M&I;7xB%%0fY-2HeQKZjY*H(4#OU%{>!l=A*pnWvLBPwBuUx%J!>j~Lq%KI z7wv}rPt|sf+`ItFn@VD)zYLq097cnw7b**H{y#~a#ul %{PrfTTJk zHAm(`#@{~z!Na#lzh;oCO>w#hHqB;DoBT;)EsMt&91vBHzSv&y2Z0WBnMF6qsho&P z_3D|QiLu RokGVU7 O}WqyG4e zpK9(V{}iKh_D`6z4mW=8?QGC )k2g% zC|^uVFXtz2nkVl4^I&*Z5Jfr{$l=~~il;8W;XzoZDN =&k=P!Y*blz+4uK>%s-3j0= zaa&80$K6ecxldS9(_rKjs3J;MbF=q&$&aVfo4Gj;gmd8F5Hy@&g4<*)(ttIcp2cEG zB{mJ}HlY@dJFYTLG(9lJ5JOsy-|&It%=3 ER$qY{f~iL~tOFwp4ma}cZ>>hH zx16X@f%=x;ynxT3@EFE(2rari#9I@D@P5_*$5nVw-e=$Z^$q_Qzy+CkJa|U^P*y>| zL93K|<18P7d;oW_r6U~V_2-N3s7dYPCQ#FFs!TPEor7(IwlI$rlc5AZDdnhPpAbkx zE0aPzN$>>MIzkL(H%@31iBO$@Y|mTtVEB=X(tWD4A*}?EHFjymf-nvE{DPyGM3uxf zw?$ZO4w<)_j`6Rzq$YNI!5A)RH8VUtlUOHe(w(iwHfGTzt!-ak#6v?tdpZdE%c_)B zOs2iuz^x6erJ^WOoy0;^`jp_LQh(j4K-oj&G~BI|(Il5lRP*l(j*oBtIphvhqSC^c zH5q=KSk5u$3E9wjI*$h3gwOQ+EW#$&=mE5Tf=vKcHDx(R$#MNL;9^28Y>rs-gEm^t z3ymb`dQlR(sf|^f*jix^_^`?2<}thNl>p|UEUeCm3Mk92j=b6UoL@<+&$s>`84`HE zCIjg%Z_eSg`s#!Y0|bp0%ir>=b>cy1W*2P(4I||-LZ7|DOnRtZ)!ePiA6Be zZ*Q{w)9tJo-Kdn*=$!harLc0$)L;NSGNb0*Vdn%Tta-DTc|~28G3+tuEO}FNg;TRl z9_38v#ZfdHkya=1?vV_!DQxw^Nk=Pi5$RSk{3xm!VR|K)Td~e8t7loFq8>NVq_#Dc z)ThyoGSX4ohoXH{^XbrPMGvQAC9%q)(sdls-3>#RPwD*Hk8tgimOsU*kY>l HT `^G z*#OqtC%xWH+2TFV7l!qWB<^{kdG6bKz#T+Y(^WZEM8!#>x4- 0?bb&RSUoq`5& zjMd0RY08t>h>C#bwxz^k-1OUu(*74T3Fkf4y{jH(RI9bx1UE;eHs?L)B06no8LOvy ziifGpmL}(ru7qS&5Csvwa5|9Ka=NADznc)r$T-25@}t?@PJi t2Zw=`V2tbQ>tI{zbb4|9OT)}4R=r{02)#0WGF_#L`8VkyiLuG>&XXJ zWF98`pcnmKr;7BLgi7oUfz@ynfM(Yml5=X@dgrD*Eh^zFlJ;k8<@*QPI^#3063LdH z3(y%4z1&V*LnL37OBC8JPU#Cxzw9Nv^q3Z*NJH;31djmLO7m|uT-8M=t43+gb=5W+ zSROyLB=W+xr4KsXZRqqKbd@$H9Bp?pE{~Qu$4}#i-A;PS6QXZGq{3`_*Iu-o1<<=8 zVMsK^trP5d0-QbxmLla+Enj3Bbb}xQ45q0ShTjJ(7ZgRMVLKo2Bk49dXhKM(;tu1e zOE!QlBPoNlN{MHfXA5-MGETQ<%m(&b!DHnl7Qk_JR909qvtgQ}y9vrJ1W$>Q6r6 YK04MotCSShzUse@)cAdY@!(2;%gg`Yw zC2`|-!GssFVUGo0^Z)*ICXXy=Ta1@hT;>1tU;KA=5AHnLWieQ *cP1~^?)&6Gyg0 m2Kg zDcBAVx8D-yQ@r9N8jC4RJt8HgrI}ZYP!Vn_FBnEH)!Us&+4duRH^_r zr?q;XaJKP1+K7uYW#+Z_4rW5>?U8CmTW}oae=9&j0TnX`GD8% XCQY$eg zt2_~v%{01c344edea`jOl|>~Re)=tC^^VsZF~4TiLvA4VO1Y7mhSsIKZ@PtuG?zsu zje5R%p8qt`IWzOTPR(W=%!jg7kcHY*5iC$^#9P@UmF?EiTHW+M( g{)$X$h&O_r7pY^Cxh~@;{qGn^V1P zteIT)RhC^{ZH7-gGvOya#}B3X=SB{1+{07)9Fc3Mot2P4=N@M>1Gu z1&6HA%$ZgCO321JN#t!@v8K#9C-+QfGmz)%s&YnL=0%txnDs(6d66E|h`{v#bXH|5 zAN?wdS;2IItB58d-3IYelC$%NrZBAKL|quWL`%EKKf0{5T#HGBuJVb?Zx)c0Dzzd$ zPJuINxlE2Z^ucJZ`H(m%T(IWpFgw#ya@LVv>gy=+gcuJk)mJv^ddv)>G@HiQf(^sb z5sOdm rSP7AXIRQ_ zZUyNFA65r>^1OQcJ|$*FSZ1rgszv-<)dezPE@iX4fv!Ti>+!_aJm+xXc>WrgfoFPN zYC^>4)!ttjh3~6R&P-ctcS+zUF{Ed{X~8T?wVY_)+$> ZOBC$RJ~n3+SQDvwS;^~|>IYK$B9%s|~T`J_+6)&Ga@Y&59_?hrv|AR1TD z)tRk6AZiRNQuo@h;(zIPH_F&?12{c-mX7tBEia=yEs9C?!l4oB=HxVQl-)FBCui}u z|9+ilXDgav+miAzy((M{=_M~%vBM xwHg_J)t2V2t%!RUG#oiu8kXKsLq^z7+y#X_;6{+9u^&lPoBVYJTM zc2>z*2JMes3Z%}yg)#vVH)lsL!5Yt)>h(&iCgE6)iLp+%8{6lJmzu!40DYY%X}f&8 z4s 2bgdyCyfy6r=9?N{|N8sauV26CzfAe@?RPjljO1q7KOEQV zV>`Ib>9t08 $&ZsgD<|v>6Wl`YMD+B{^NOovHc_ z44Ovk=fH=rLsZ1i-z|+j9BG)F6&i$L3cv6R9+zy `6{?URVOdrw #%t&XX-wQ?kW4 ziIv_I&?ot|1^uiJgoqF7xG}NxX2N9@&}qqB-$0~7Q|xsocTHI-(iG!1Xkx|;(HJ#1 z@pfXWEo-`H_sLc_K}lBs^t*s2rSk0xIv`WgZy@P95wy!SU_G^gp4uV^8X1OY!t%K? z^K3;|=YLCO#kg={ly^w3uYdT5fB08_`HTEaTV)JLpeqxaCqp~{ba*=V1%W%sf{)eO zs>TT8!w|;sUeLO&_?Xr)3upyN9-TZhgeE&ne|-3T?MsyU2hrwiIel;eLlS_{B(|pA zRgme8TS{s~*BR{Zzcb6Qaw_KU7W)^1Kap=55PX{_9$QTb>cNm5N9UX~mbyD`V7u4f z^2nIt&;GD|Gs@Etyus0!Fi|QKFafrx=q_1lvjQkohggkh-q}Jw&=#sl*;D_=|MI`* zq o_kY@S$mZNc}tf;f3Bl+N$>N*U`4iN7- zXb!VlS~Wau8iyQoE)1C8;2F`j!L%9)})!g9*_xeoUain$**tb(k@Y=`9FdYdw7C z9Rw3v>H6!T5O03a=OuwT#Z55IG9Ye75dPI{Cy)*c+)|Q!J6->Qm7OMy4RHcarw#(? zRf>3}6VB2T$MXCViF_&8f+31FS}Mfmzd|?JfEs19tqrAgM%J9=#ASx>tp0P3x_a=> zK>_45ZPI7_a4bntc@drI-R{h(p11EeT;o-uJ-`M!ZO^3I$l%;!7n=jo>9Jw$+29GC zw ZC!lJYjxfQwt6vJT?d(_i8}G%Izz3v=6O!p z3Pm@^B8qbrv~M}B373>RlP~4n jQOg~a_BD1_0c`^DmkIroMIwMcK1I~{=5~M zeya|pT^U;J^guZaQ+PGJ|0S!;CamLvNIxvX-|pyw0j!=E!8d%FIk#<$lm3 z!FohCoQ~xtKK4oA5w|1@9XzAWp`Xuowc7=2ZN?`xb)*v;^zsV7IY8^D*;a!RPP*aZ z$cje&sNm)Iz+!^(x7vx`NA7Z?Ri8He&^QRwk4^N%q_djzNx>| Y>2_Nt@|FB6SS<1{w@Q1to;L|3pk@DwrE#@ljpub5+mo8 $magJ$2le|mo-3#mk;ZWeQOAb*;4z+i{~BlldinE`!!;)l3`xCL!*qAP z+u)-l4?qbJw{_%wejAwQL82Hu_1vy5q_;Z{yq68l;U(67^SOr~%y1g9K1=W@GQ
0AJsfN@iZx{6}4DBUJq|2@EYi=OGIBuXzoL|*K`-&T;(UImK$=cU}Pn}32< zXlA}M3sXxOhbqlUqyxgpPJ(%TO&~aoMjyf6-gv6d*9oSILT!t5j!jOhJREs9mKCer zM!Ayd39X^2U8S8He_Gj=41{A3Kcz-)SzTzUmT-C`7Fg#EZI>n$LuV?w1JrHrt-|*= z1wOk%-#)*6{#RcdyxLN zL4VBz2VdyO&z4_4zy0O&$Il=AGKk;FurFMImLI#tBn#1eLuH4tb3N=KJL-188p4)9 zh&T}OCw3*bJp#42|LMP+|0dRQ5nx>CS3;KuaUy$;Kw5LCAz(rzcd7-Vpfmdbm8c<$ z51`vrH{e$UlsIvg{FK!dXkt2wK|6YwqmSxZgjub?xRj1@l3(8NkarX1<) KzRLAdZbo+M6^`%BWZO~!M=nJYkSb#Gb`jdP-tjiCvs%gU_(onJcq1BB?{y4Nl z_ECo~4;oN?j&{VE+jPy-QDws|FwFRAOKor Suc+o;w>DmqVvUQxW`ojJdXgiusw*Am+l6)CGqVb0ZKP_L! z_BXDF#Q)VZwJlZ(*S21Q858%=BWM)co>P-oIpSK`4=iE*371)^aPX??D#O7}gfpNT z(F>gX(po0@XLv`VLhjWBEn1qX513^>ft9Uf%QwO0YXo;waBv_vdhdUteA&}kMJA1R zr<`a5xpiM`8TM=stG;p4#iUWe5yZ9`R)Ih2A)e!T=H&It*xyG%KKhsO90q=m^Na`n z?!6KZ)esp(!jes=(V*!$*HlfJ151>19hmMzbrC@f^~u~&DOQo_;NB WB3mq DpoqfhaiLZWNoy(H0J)Fqy~KsS7#)Kh=yu<7 z?opwP>CZ$@CLC@0Es?o8Y~VH~8YEzCONw|}7@mN3PA0LUnM;siR= l>E-M=JRp6FUTgmU8x2PTWt)%}%l(EJ@SOKsV|dYLSli z vWV-}0;%GOV{l8up;o z-O{tkKf&2Q%Vfq;Dk%LP$g%n+w1|i515O>v!JU7J7O^>hn9@u9iq$PdE*3*?COYR9 zGppqCyy#)39O+hDqSh{c;qBVO5$T5a_&5BLl9*PnELz=N@n_NXNawZsfNV<(i*7Hq z9}@S_8EK&?$t}Ysnd0n4mL?^xb}O*hm9ZXuhtM@ASu4qn%fnr;tIYmZ%Q?#j$n+8f zd9|pmqx2?z(RR~@yV~L(WzO#o@`wk??Zy$4WV)mJ=6Cnm@shv#97ic*K0I-=I%65x zMz;*3@LbJvN#S>hjg{dfe4$aE^v|>g&zwip`ObV3#hov`t~-ZX`)bX-T`t@>&jc8c zIqmBjI9Jon {tr%#(OVGr#9E*j9#H8l%73 zvVURi1sv)+=XAf1|7l8p7MXb0e!J1=&j|mu=){@fZtq5&S7!%0daUJj-7jWdX>sTG zh9LCpMJh{e{?OD;g%Pg%lVT);M`^I{Np@MH*!q5#o9TxnLT-;M+c(`UkMvjU(CmA1 zLZ9%aX<_tpCpKnjz!t&SdrPY=C3*^{fOgd^HGpji!0 |FY^J_ z>BAmXeoi&$R_BqM7Pa3zd<^TORrR`ZYsf4KXI^l~&r5-7XzT-C?mdI$BXl{d_e3 R?CDWiB{S QD&;@XFLGAFV3ZpxSc1O$ZYRbTFz)j9%O$jTo-XwNl{Ud-6@l} zJ<(>jF{2XPoW|RfhjX|1g;H~6sma=PU*bWq`*VAYhoJ%T%i9&izQ7h7(u<~{O_Eii zKl;*6*S2f(h%o+lIcVJI(YXftk=GL$Hl`-$zToJufcXG6!UTvy=`J~$u=1N>ol;d0 z>kQhcGd%zU(WaSYr3 B47yR*3+nH=e6nBM-!|6=|Z70Va^jP+|U-DeNZiwtMpt$MB* zkXVni5O9K7|K&`hoR2t)Bst`Lo~m`Ot4`OtT{MJiKPLE^u??hcnyln_L+gs`#4@yN zJp@w$B5ET_$KkREbdO5W+y_9hziHxHA`eQ(-CsZP-I Gc-NP|q OE3+8-T*fuPC#ylW=~8Wt^C$T+@rN&wA1xJ|BkU z@?_^UIG51G%27w<+uIWBXQP{nTJznF$VbJV%#cMPEtqN`IT((SF0OQZZYfyw!Lt$L zEa%(7&&Jv qE86HYcM5Ve2qCS`iWvUNL8g3}QK;RndL&TkNZrPU z(;U=?>1|E`(-e^mXX}i4XotW%AFGp09|jtWPQ*SyIk(r|!fNihp0~O@z2hZri)xHs zQZlP}F3K#OZFn@xu?OyeY1v9p&Nc+Bi(%%zR42Lm07%MSo~(8;CIPD3%G=1?YEC3u z<~Q=vb(B6!=m}HK_93vE#{%!*^^B~2Xo0DBo>C$Pou$=G4rVJ6wX2iYAi)#ia}&!G zPUXYBbohZV#_pfsWL|s;X_9d>Tn{!8MM~$a6s$(ijMtzWGY2W<>6QK=0eU5?!;?CV zh-aUl)(Z}sZ*L7SGXKOX+A}g^egUl@{8MDG>f$gQ;fxP(l`uBR;qNpvUpFO6I5{M8 z73c&Q+niTE(J$x3N=-LsYP8mF?mbAHrfaN5E^1LWu7 q3cz5YO_`wx{B3+X~TG*K>le2$A$cT*ZnOWS}|Jpf}C1Qol?b}cY1)+XS$HX!nS zx1x^rq^C}4GtIz`p#Jth{OA9^_8`4+gUp5TascKgiqSdf8*%W9FyMEcrJ5NpA>PX; z-p08^+lo}?GCvdBxUtZ#eNcuaGc5#zFSRxfIiV>lwW(B{L3t=Wx_e-}#Qfg(!8!pI zLNFW<@GF&$aO;434_^_6bw`!A$$M(=VfyeLY|$p#6#&j=f?uI)v&olbM?m6V7!Oh2 z3prCQI3LmPxH#1*wq}TTBDC#KF3 *g)!b*+r@uSO{q_gF7;2Cb&7+29r~3I+5Mt?Nr)ZM?#HKM>WygY&-& ze870ZWcU)V1_Qir^2q<0bEPfkDlaW#IIWdmK<;YSqe_dly!7N5F`ancW2_&mh-!FA z)8&c-D*^PnVHu)j1fKHHl&fWo;PRluseCn;|I${E+X OhclaL&Lg@bfq=?;#45`})#{y92#Q$$#hGm8TFN z)acuM#G01-OHzo@r&{H$zn7Gp{&X5dUoSqV QHOKJ_AwAj}^7JAp*MdsDRn4gWbyT0Vz-Vs#@GB^F zOZoVMqdEbtV9IrV*3a7WA5k-i+NCU#e1@dbs6+I8aUlI!omLho?T9_03LANhc!8~l z^IK|VdUUeWw(=f5mpxVoW@wh tlG+D0HVU}yz8NREOD?mIq zxy5pNUVK_2kuNVWDdG5#?mprd4R{)t-xn5oQQ7D@#?qz11oNx*^m*N$fKzC-CRI7b zXyjB;jq0s!S%yB!=LN^IYPeYuskb~aqoxI|=){m88$i|Rl7 m#xDM+M-H(Ctv0ELubx# zR8e_SO%K@Gq@n1?Z}WnqfERBUaCdqHySh0W36auhjV@BNib3*Hp+`AA%gD|cWjPJ; z!~eUElDIpjQWT;3Tm7m=NI{>dfv{I+{f>5Y $N#lxZ1h;>4}F{N?0Rzvj^c(b$9;V_Qmz7XtV<$+xyUlSdlc!}o}HrVi5Z zU2Y`VTM7DCwl62k4@{3MS9L=8@=w2I)+E&jx(c^L-o(A7VU#gE6^e)IFQQgI!J`f} zv$#+Nhif52E3-8~4{v(Gc6eHyzlcY@qMx0_>UKD9cGWT3hk3p@-ho*w9ak59_vtbT zy%kQYpB_RNuW(y^PjtEt!{y|0(ke=IDJ04gPec`*Z*GTjlXqoqeO-4j`8Sgpo9JZs z`SH<3H1Fdh;h1Gr&N>psEw~%`+KL66Bm-8pZbuslvQmxC9p<)TVL5UWo}d-2T44G% z#N!7m*lHf!BupLEhMX-W$0%s*%h_~G`X`Rk;xVHV#e_{6_LN0w+McsWRyUo#0xse+ zsp&BJ+%i4jH@%{RN&4Z0`+t4?+VSLlQ2v?!i926 PX<95(Y$L`J`a0(x8qTbe^ohuq1uK z!DR(`ban=Dl@B}z31kN7AxsDA0lVFqUImO}^%x+GDEs)4ptDT+8yjK3S7%JxY2mL% ztH-I$ET;rG>4B*l77}SP*RaOb&cI*uwx83sgWzw3VZzX{Yfr?}55FwXqul JEz@6{WFiB@&=5bPyYJJTYgui-`D8z`Sa)g^$mB|{B|L*joup4mBf}v zM`pgjupex@3#o_SK!(L8 tShK2yO8ZNnD~O)bS$c8w zaN(PlYy@k7b&51S_zGXYe*OJ-|F5Y{ {xfKLCt%iL6;6~7TCH*kx~tXA{8RYbtbUH4_&h}qYOTJseb3?U zkpIx|+_cSk5dGb8&XeM~m#PD%-uue~BR&?g%ktyL&VMlC0DVLchT!Mbjo6K7ydQY) z0}AkC<$Utv=2ji*z-B&3wS3ZtGhMI-?pbGxss>v9L;Q;7L%8SYpnlHsZ^8@De=~NT z@8y5;JJ!z_@jH0g6`=f=fqoI&!v+iF`mgo=yu-g4jb5UhjfxKVnuAlN"p3ja*} z-TgMzJ*)S`-gF62I>HMNd)kR- R4W3b9HR6tdw1jw)w)|qMDJ%`Vo#M~IC