From c942c303843e6c27f008d74e2d8138328a592e7b Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 29 Jan 2025 13:51:48 +0000 Subject: [PATCH] Update omr-admin API, disable fastOpen, add vpn1 management in omr-service,.. --- debian9-x86_64.sh | 48 +++++++++++++++++++------------ omr-service | 14 +++++++++ openmptcprouter-shorewall.tar.gz | Bin 4154 -> 4164 bytes openvpn-tun0.6.1.conf | 4 +-- openvpn-tun0.conf | 2 +- shadowsocks-go.server.json | 2 +- shorewall4/params.vpn | 6 ++-- 7 files changed, 51 insertions(+), 25 deletions(-) diff --git a/debian9-x86_64.sh b/debian9-x86_64.sh index bdc55f1..719a1bf 100755 --- a/debian9-x86_64.sh +++ b/debian9-x86_64.sh @@ -54,6 +54,7 @@ IPERF=${IPERF:-yes} LOCALFILES=${LOCALFILES:-no} INTERFACE=${INTERFACE:-$(ip -o -4 route show to default | grep -m 1 -Po '(?<=dev )(\S+)' | tr -d "\n")} INTERFACE6=${INTERFACE6:-$(ip -o -6 route show to default | grep -m 1 -Po '(?<=dev )(\S+)' | tr -d "\n")} +[ -z "$INTERFACE6" ] && INTERFACE6="$INTERFACE" KERNEL_VERSION="5.4.207" KERNEL_PACKAGE_VERSION="1.22" KERNEL_RELEASE="${KERNEL_VERSION}-mptcp_${KERNEL_PACKAGE_VERSION}" @@ -71,6 +72,7 @@ GLORYTUN_UDP=${GLORYTUN_UDP:-yes} GLORYTUN_UDP_VERSION="23100474922259d00a8c0c4b00a0c8de89202cf9" GLORYTUN_UDP_BINARY_VERSION="0.3.4-5" GLORYTUN_TCP=${GLORYTUN_TCP:-yes} +# Old Glorytun TCP version if sources is not enabled... GLORYTUN_TCP_BINARY_VERSION="0.0.35-6" #MLVPN_VERSION="8f9720978b28c1954f9f229525333547283316d2" MLVPN_VERSION="8aa1b16d843ea68734e2520e39a34cb7f3d61b2b" @@ -78,8 +80,8 @@ MLVPN_BINARY_VERSION="3.0.0+20211028.git.ddafba3" UBOND_VERSION="31af0f69ebb6d07ed9348dca2fced33b956cedee" OBFS_VERSION="486bebd9208539058e57e23a12f23103016e09b4" OBFS_BINARY_VERSION="0.0.5-1" -OMR_ADMIN_VERSION="be866bf752119b3460d907f92572fcac773c1a97" -OMR_ADMIN_BINARY_VERSION="0.14+20241125" +OMR_ADMIN_VERSION="530d20c6b482d491accfa4ea5dd44afa5d1eccdc" +OMR_ADMIN_BINARY_VERSION="0.14+20241216" #OMR_ADMIN_BINARY_VERSION="0.3+20220827" DSVPN_VERSION="3b99d2ef6c02b2ef68b5784bec8adfdd55b29b1a" DSVPN_BINARY_VERSION="0.1.4-2" @@ -224,6 +226,7 @@ rm -f /var/lib/dpkg/lock rm -f /var/lib/dpkg/lock-frontend rm -f /var/cache/apt/archives/lock rm -f /etc/apt/sources.list.d/buster-backports.list +rm -f /etc/apt/sources.list.d/stretch-backports.list if [ "$ID" = "debian" ] && [ "$VERSION_ID" = "9" ]; then apt-get update else @@ -509,15 +512,11 @@ elif [ "$KERNEL" = "6.11" ] && [ "$ARCH" = "amd64" ]; then elif [ "$KERNEL" = "6.12" ] && [ "$ARCH" = "amd64" ]; then # awk command from xanmod website PSABI=$(awk 'BEGIN { while (!/flags/) if (getline < "/proc/cpuinfo" != 1) exit 1; if (/lm/&&/cmov/&&/cx8/&&/fpu/&&/fxsr/&&/mmx/&&/syscall/&&/sse2/) level = 1; if (level == 1 && /cx16/&&/lahf/&&/popcnt/&&/sse4_1/&&/sse4_2/&&/ssse3/) level = 2; if (level == 2 && /avx/&&/avx2/&&/bmi1/&&/bmi2/&&/f16c/&&/fma/&&/abm/&&/movbe/&&/xsave/) level = 3; if (level == 3 && /avx512f/&&/avx512bw/&&/avx512cd/&&/avx512dq/&&/avx512vl/) level = 4; if (level > 0) { print "x64v" level; exit level + 1 }; exit 1;}' | tr -d "\n") - if [ "$PSABI" = "x64v1" ]; then - echo "psABI x86-64-v1 not supported by Xanmod kernel 6.11, use an older kernel" - exit 0 - fi if [ "$PSABI" = "x64v4" ]; then PSABI="x64v3" fi - KERNEL_VERSION="6.12.1" - KERNEL_REV="0~20241122.ge695ae7" + KERNEL_VERSION="6.12.10" + KERNEL_REV="0~20250117.g773b57f" wget -O /tmp/linux-image-${KERNEL_VERSION}-${PSABI}-xanmod1_${KERNEL_VERSION}-${PSABI}-xanmod1-${KERNEL_REV}_amd64.deb ${VPSURL}kernel/linux-image-${KERNEL_VERSION}-${PSABI}-xanmod1_${KERNEL_VERSION}-${PSABI}-xanmod1-${KERNEL_REV}_amd64.deb wget -O /tmp/linux-headers-${KERNEL_VERSION}-${PSABI}-xanmod1_${KERNEL_VERSION}-${PSABI}-xanmod1-${KERNEL_REV}_amd64.deb ${VPSURL}kernel/linux-headers-${KERNEL_VERSION}-${PSABI}-xanmod1_${KERNEL_VERSION}-${PSABI}-xanmod1-${KERNEL_REV}_amd64.deb echo "Install kernel linux-image-${KERNEL_VERSION}-${PSABI}-xanmod1 source release" @@ -614,7 +613,7 @@ if [ "$KERNEL" != "5.4" ]; then if [ "$ID" = "debian" ]; then echo "MPTCPize iperf3..." - mptcpize enable iperf3 >/dev/null 2>&1 + mptcpize enable iperf3 >/dev/null 2>&1 || true fi #if [ "$UPSTREAM6" = "yes" ]; then @@ -625,8 +624,10 @@ if [ "$KERNEL" != "5.4" ]; then #fi fi -apt-get -y remove shadowsocks-libev >/dev/null 2>&1 +echo "Remove Shadowsocks-libev..." +apt-get -y remove shadowsocks-libev >/dev/null 2>&1 || true if [ "$SHADOWSOCKS" = "yes" ]; then + echo "Install Shadowsocks-libev..." if [ "$SOURCES" = "yes" ]; then #apt -t stretch-backports -y install shadowsocks-libev ## Compile Shadowsocks @@ -1229,7 +1230,7 @@ if [ "$XRAY" = "yes" ]; then jq -M 'del(.users[0].openmptcprouter.xray)' /etc/openmptcprouter-vps-admin/omr-admin-config.json > /etc/openmptcprouter-vps-admin/omr-admin-config.json.new mv -f /etc/openmptcprouter-vps-admin/omr-admin-config.json /etc/openmptcprouter-vps-admin/omr-admin-config.json.bak mv -f /etc/openmptcprouter-vps-admin/omr-admin-config.json.new /etc/openmptcprouter-vps-admin/omr-admin-config.json - if [ ! -f /etc/xray/xray-server.json ] || [ -z "$(grep -i mptcp /etc/xray/xray-server.json | grep true)" ]; then + if [ ! -f /etc/xray/xray-server.json ] || [ -z "$(grep -i mptcp /etc/xray/xray-server.json | grep true)" ] || [ -z "$(grep -i transport /etc/xray/xray-server.json)" ]; then wget -O /etc/xray/xray-server.json ${VPSURL}${VPSPATH}/xray-server.json sed -i "s:XRAY_UUID:$XRAY_UUID:g" /etc/xray/xray-server.json sed -i "s:V2RAY_UUID:$XRAY_UUID:g" /etc/xray/xray-server.json @@ -1244,12 +1245,23 @@ if [ "$XRAY" = "yes" ]; then sed -i "s:XRAY_UUID:$XRAY_UUID:g" /etc/xray/xray-vless-reality.json sed -i "s:XRAY_X25519_PRIVATE_KEY:$XRAY_X25519_PRIVATE_KEY:g" /etc/xray/xray-vless-reality.json sed -i "s:XRAY_X25519_PUBLIC_KEY:$XRAY_X25519_PUBLIC_KEY:g" /etc/xray/xray-vless-reality.json - #for xrayuser in $(cat /etc/openmptcprouter-vps-admin/omr-admin-config.json | jq -r '.users[0][].username'); do - # if [ "$xrayuser" != "admin" ] && [ "$xrayuser" != "openmptcprouter" ]; then - # jq '. + {"level": 0, "alterId": 0, "email": $xrayuser,"id": $xrayid}' /etc/xray/xray-server.json > /etc/xray/xray-server.json.tmp - # mv /etc/xray/xray-server.json.tmp /etc/xray/xray-server.json - # fi - #done + for xrayuser in $(cat /etc/openmptcprouter-vps-admin/omr-admin-config.json | jq -r '.users[0][].username'); do + if [ "$xrayuser" != "admin" ] && [ "$xrayuser" != "openmptcprouter" ]; then + xrayid="$(/usr/bin/xray uuid)" + jq --arg xrayuser "$xrayuser" --arg xrayid "$xrayid" '(.inbounds[] | select(.tag=="omrin-tunnel") | .settings.clients) += [{"level": 0, "alterId": 0, "email": $xrayuser,"id": $xrayid}]' /etc/xray/xray-server.json > /etc/xray/xray-server.json.tmp + mv /etc/xray/xray-server.json.tmp /etc/xray/xray-server.json + jq --arg xrayuser "$xrayuser" --arg xrayid "$xrayid" '(.inbounds[] | select(.tag=="omrin-vmess-tunnel") | .settings.clients) += [{"level": 0, "alterId": 0, "email": $xrayuser,"id": $xrayid}]' /etc/xray/xray-server.json > /etc/xray/xray-server.json.tmp + mv /etc/xray/xray-server.json.tmp /etc/xray/xray-server.json + jq --arg xrayuser "$xrayuser" --arg xrayid "$xrayid" '(.inbounds[] | select(.tag=="omrin-socks-tunnel") | .settings.accounts) += [{"user": $xrayuser,"pass": $xrayid}]' /etc/xray/xray-server.json > /etc/xray/xray-server.json.tmp + mv /etc/xray/xray-server.json.tmp /etc/xray/xray-server.json + jq --arg xrayuser "$xrayuser" --arg xrayid "$xrayid" '(.inbounds[] | select(.tag=="omrin-trojan-tunnel") | .settings.clients) += [{"level": 0, "alterId": 0, "email": $xrayuser,"id": $xrayid}]' /etc/xray/xray-server.json > /etc/xray/xray-server.json.tmp + mv /etc/xray/xray-server.json.tmp /etc/xray/xray-server.json + [ -e /etc/shadowsocks-go/upsks.json ] && shadowsockspass="$(jq --arg xrayuser $xrayuser -r '.[$xrayuser]' /etc/shadowsocks-go/upsks.json)" + [ -z "$shadowsockspass" ] && shadowsockspass=$(head -c 32 /dev/urandom | base64 -w0) + jq --arg xrayuser "$xrayuser" --arg shadowsockspass "$shadowsockspass" '(.inbounds[] | select(.tag=="omrin-shadowsocks-tunnel") | .settings.clients) += [{"email": $xrayuser,"password": $shadowsockspass}]' /etc/xray/xray-server.json > /etc/xray/xray-server.json.tmp + mv /etc/xray/xray-server.json.tmp /etc/xray/xray-server.json + fi + done fi #if ([ "$UPSTREAM" = "yes" ] || [ "$UPSTREAM6" = "yes" ]) && [ -z "$(grep mptcp /etc/xray/xray-server.json | grep true)" ]; then # sed -i 's/"sockopt": {/&\n "mptcp": true,/' /etc/xray/xray-server.json @@ -1451,7 +1463,7 @@ if [ "$FAIL2BAN" = "yes" ]; then apt-get -y install fail2ban python3-systemd systemctl enable fail2ban wget -O /etc/fail2ban/jail.d/openmptcprouter.conf ${VPSURL}${VPSPATH}/fail2ban-jail-openmptcprouter.conf - wget -O /etc/fail2ban/filter.d/openmptcprouter.conf ${VPSURL}${VPSPATH}/fail2ban-filter-openvpn.conf + wget -O /etc/fail2ban/filter.d/openvpn.conf ${VPSURL}${VPSPATH}/fail2ban-filter-openvpn.conf echo "Install Fail2ban done" fi diff --git a/omr-service b/omr-service index 06ea52d..9021e59 100755 --- a/omr-service +++ b/omr-service @@ -190,6 +190,19 @@ _openvpn_bonding() { fi } +_vpn1() { + vpn1route=$(ip r show dev vpn1 2>/dev/null | grep '0.0.0.0') + [ -z "$vpn1route" ] && vpn1route=$(ip r show dev vpn1 2>/dev/null | grep 'default') + if [ -n "$vpn1route" ]; then + ip r del $vpn1route + vpn1gw="$(echo \"$vpn1route\" | awk '{ print $3 }')" + ip r a default via $vpngw dev vpn1 table 991337 + for route in $(ip r show dev vpn1); do + ip r a $route table 991337 + done + fi +} + sysctl -p /etc/sysctl.d/90-shadowsocks.conf >/dev/null 2>&1 modprobe bonding >/dev/null 2>&1 ip link add omr-bonding type bond >/dev/null 2>&1 @@ -214,5 +227,6 @@ while true; do [ "$lan_routes" != "false" ] && _lan_route [ "$gre_tunnels" != "false" ] && _gre_tunnels _openvpn_bonding + _vpn1 sleep 10 done diff --git a/openmptcprouter-shorewall.tar.gz b/openmptcprouter-shorewall.tar.gz index 92957efcab04f4eca8eb09a1b98a997dd26d155f..fcc04f34f15f1a5273a4cc83694f962f2c58783d 100644 GIT binary patch literal 4164 zcmV-K5WDXmiwFSK-F#;N1MNI(bE8O-{T2O+3fs5S9cR5?V{ho@Fd&IF0tS#hp124C zOV}nx5;{Qb@lEu9-^?mN2+6J9X~{j;OWGl*tgOs>WMyVS6%&84hyrKw+q>gI4WQF% z(JMgyTJOSrz18S6o2_QI+jv*2*IRHQwIkLkg;f|i0U_@K-;X{=w=e(yDV&y0iTUIQ z?z1zSk#d<--Dpw`6HIlI=tl`D`+h*Y#e*NroyhYS#JTrZ5pjXSb3@1>(UTXF2XE${ zljvpXl9Rc!ASt(U%IyT${nXct5pR)Z>GVyYbjk~stf?HwncCP8B#sj$)8aVY&@7D; zbAwuE7+^pp2M&iJvV4JAdF43qrrZ^X6*%eHu9AX$vSw)qjSioDH; zN`iIyt6?+GMb~$A$#R+R6R3GJSJdQHX}f6XEZkh(+nr9nsJugH=q)#E+pcx; zy=AJST_qRuT+w4Rk_VE#$;?3Yv3Az;=Y zyvJ2Qok9gT3jXpX@E)Hc@?Q8r8Zi9jMy=i=_b=cf+>AiWb>`HwSm-!r-hJQ%F9dx^ z;JPIAAEIX`aQ{wT{1usiD+%1G7lOCBUqvqQA_A7R>IYDM?!#<&LDXt7bpt8}sy7db z|3DK1bxagD3?XmeF5JMG5q)((^CnPO@h0vfbcqv^CE~&-cbe3-j}woCJ4f^=st-d@#09T zM88M0zaLfs3L{fDa=cjx1{R}-Xmx_ zh6-j0oE3Kl-prOUlbb$GmgnF%9%jyCcpg9xxzHof@biTq&R4-hcpkz~Ph6VStCc=3 z7u;i1j#i8R~*J`BCb1@&GZoxpSMXW$p2C+6MA!UdlRF3M%jOpefthpWd&H;f>M z(j~>n!kI(ad-oCC$}_l8U`kd?h>F z=f!@Zw`ux=he`dS{$rLod7taawSR;tX5t6a4@`c>!*J||%4fHU8)6}n3njzVEP_Tt zlkQo#5JF#KlSd<7;s|r*o zj{?u}t>?tQ6RZc~cry0bfA9dEoc*u2+s(rMzXhbBEj57Ox;6#8HN1t@-8=ug&3E-y z7c4-#-R`pIKeb~1zX{yvrp=3@(W}!yfCU95ZDed=8zrP=wgQ%%wPFSLJ;2hRd6Spp z%Gme(x7O(7pZ~&tG5_BJzTo+GLTK@TOr&a9#c@y{o|8Jm*e69OGhr4bO1ANCZ z0JS6s4*|XrBzwhD51b1`wj&YTLzcnk=`}+h$SR)%CdA+^DO(;loK@jE;*D!e3!19Z z=q1j#hy%4kdAoG$aLjB7>0C8(xt!h_PxJyl|bRQKj2b+BDH${19Qp@;b+P#YgUxdX2nNb%ibm<2X`7hFGLsUY|ZusO({pZl1{1(!>KF<8$C0Z?r zzu4#{V9KO!bVFWrUbE31jk^L<6 z!D!FC1>8sEDT_o1J0(auU<(422Gpw<0ODY6plGwX*!_qNY$C`HojWD1w8Z=XeCf*&sK{t|drJ1sI z*Q+0~ApklI%K+PR_%`VLKr(tqtbQMQ-+;Q`LK_sK9KHp8*^q7_q?T%T~03O&=yhd*W5e1`hA9aAl&3aS9f1mdvYWPxTpMt(OgofX;!n z3#0DKiqxxqbb=}bz16uJhG=+L7TxXKJ4x;6<$r|ue?oIDexRw!T_S`o!GPt67jo4` zLs}}uE3A#G8#+k0Bx8%%d<{Pu8~tr;Y)1gUZb^1WxEECbRVrD6Zub>_U~aKUS9crr zJM^fYa;P-|D82=HqY)L9Nh5s@rv%zqTu1YuPa<5!c$x@6tHGU&`G?mt-q3M5ESb<; zSnT)Zfvxk_uy=Cy2PQ??__XfI%dBI>mwg^5St!9yzNl#(Ht@@Gq0&AIcGEr>&)FX?=)w!sefxFCLPfEz?izS|bw){Mn z#?ofhcc9pNrGJ6(aU6&NV>yJ;G+-=sPJq!I(UHZ8e}r*0!0HLw2#GuQ!R5rK|33R8dOKPTSOq_1F$&$Ph(a)@^XfyeTnvizpLT^f}~6R%MgFG9}f5 zTQLcC@iZ@XFQC_m_;~LcG2*W!%IAtVWx-~?k#SDvXYT|&`gt55oTu&#RahAEvTB=x z0Y*6HDk%I&ADN7Yph&!7gGr+aZKNxb#pJ<60VfRe(*|p)DPw%<$ry+d64};JQt@F$ zOl{HGg{_x$e1yUHi`a5S0^Ci9A;646jLB|Q3>A0`UBo+;A3^)pZK9&2Uv$tuo4zrY zB{M~8h84REhU)VW2T&76IYaPr%NwH2T8GcGK}6EE;D81ynEJ7Lt!lT>X@<<)6PA>r z2SAhsijRXnW_@ugtBR~jz{wJZ2_EQ!PKDMM^Y<%#qjjdj%2F`g54$^>>WE*_}x9C$sJR~rZ zf0cT*^}U^$ODc^5sRd>g#RyRPc?{vYot}G(sc1+?{jw88sk2TjHxtg9o@7xJHrh<^ z7OH)A8nP<0>BERj{syX;hCoO}QFLHg+7i;PPLjXCs98x$H)NQgdhet`n)DB^b@*#+ z{$bRBa}o+@H?o*aV1_fsiTJUZX=OYE5T_6CVD9sZ4Ra(z3Tm}RurMD~R5DFi#l;Iu3b@H*t1=?uQrjB6fxL={=#UnN7cS^v?brb-R`>6MRT)pZ)mT!US=;%L_dtDY>* zsck>zstSyfj!Po!54w*fU0Y>y5(}`NgW23zoTUe-&TZGmhtvjhKXiS_zr zJ8!*$+1-Ex_vMa39MNY-*SIw1$sG*fm{^Awi*xQuw$O$rGifWW_4{mjG2+eZBo~#L z-4}a?|8fvQ#CdEP`}Y4f>y3ByR;^QScK~X*|EJY%70>_Q0&?d+lRZBeNmoZs_`fSR zaHg*NmD_(h#m=Aac;^q=kdw3_@w=6M?^S3i`d)=La}MZiCH_kLh<1E9ircyWhoj$) z!WdTIFrv$TMvB87K=gZ4KzhYr$%<^AScrB-dU&i|*xWspDa zK(=eUko8^2#x7)Y7qYbr+0G(67mN&W^-hfI!X)T0R3k=RAnM1MjLUpS162hq410Nx zFY{q?!i=DrKwlfC@At#fDN?>aOAac1;J8|a{#9$hGCh-2gcg4a!pL7P-RV)c0q^tw zt!6iO{-*&tT=@UDfY0%UaL2*-fFax?B`xv$z3o81f> zr?+;{#ov2M)8#FSa*lIcVi%|6(@+u|5JK{5FDrR-Ioi8|>FMd7kDl%xm|+(9ejGZpU*4S#ngHE) zn_K~kSGEWDY^&F6wpzVrhke&%*><<{4mD3$rwrCn?1Tut3xgp39NnS(|4=xqoFVfm z2;FCAu|TyNYPj*N5v7>MEY*(+rW^(#^8AM&TspBA_{g~r)-iH{!gC|YLGhCpp$Bi_ zUZD78<)Z4+@lnRDmT{{ByB~&{G2t!Ls+_$ERL*$8k~NiK7*m@Xg2XVQWLgZP8=9pt zqOKW`Fv(?VN(N)z%9b#$RDSRt&^bS~w6Ubp4`RC4X+&NgSm61YfO#7|JL&r!#11WH!DB5{@i;=%MUGmx9~%}+LVlED~4kW z#l|hJwOh{M&4R=pdzs7sv3}WNw>h&tu2?165O!I6;cUBLx7+O%3aXMdkTug*&E4|8 z8{d0DRP&=k4O>Mny1uVVR;yy4K+Ri)q9(6OyG0|%cMEmzbi2i(@*bg)x7x04r`av` zmZ?tmmGqZ|qHMP~hSuJ(kGBRNm+W3{3exM>&VSF3-SEMgxzRDK$$mIs|2a_2cWk=_ zL>$*_x3K;1vZeih6WF%@AKfs*cD-G1q8c)t)g*tE)g4IjtJwC5XFtRnS$+pq`3wQ`OC(v@8CGjj4b{q@uK6JttgndZp zx+n@B;%6sx|At1eUcCgiwANz-)NIsI@`)q5w#^$$_7!UaD-rC-p(f!d`d>!b@z5QNKO_lXRN7bj9Z z{xv53{jd(PFf?~#$6G{DpmtO^f^XkglIpP?dKM~hN9TO@v!+T2Az8H~W5^5m9)qUi zP{FK#vtrJ{o7pnXWadw^)dl#ChlTSPU4+m>F7yaA{K5~S z&pgJpcpgQ~B(k}}35FW?z8gO^lhi=qO{>qgnsu%NKD~*rog^>u3;k`=A3n_3 zOZNLbbM(H@lNqQKWgeKk7a3O-e#F2|f zBM-_OJvk7;xGr>W=s{=tnJC;&hAA|Td9^u5cDJ%BC{s~FRITbzp&|-A$G4sn|4pzN zh||e9VE@4bbc@gbIvuXG|8D_VXiE&>x2{bIZw+r@bq~(}-tPSGmCt|P1a5TG=0(xy zvm_88|JjN*F?O(A1=CVnL07cRauN3*5369|&0bC`wl&wbD6i&~TdeqW1nplgaO+-=f|HbRPYBPnTGp2*hKU}~6F z1wWI_mqoDV*-G<*AnDc)*~9Zbssa`jOT9w&ip(M!Pmer^hNhEestox_le0yF*i@Y$ zFg`)S>>5jGs40qeE32cl$0k$g$bp0u9(o3(F%0=Jr2mx!=&EmRl}dOk2-k~KzWOC_ z!2h?~?c)9)AZJVe{}%8C{@=hV^0n^&0`7Wc4Dct80f;3zdI<21Al)mLdEi1IvKxuu zJ!Cn2kzO<8k*xA*V1f+ZlJe#8hO-7-C%kcu(}Jd|Bzj5mEqSsp*ygES-sdLoCA z)f--sbBL*G8N6_vr%|QbO4c+n@V|?3#1uSZYvj8#qP{C{_RD%j-xlFngC8 zv+(BcaRh~1btv$PXDc!{De$wIyNZ#hnmI|)M#h7en6)@aWj+TX-Z}|I-qVPT_T~BT zc1sSeT_%S#M)&+j!n={MyU|r3!stA&V&n;|cW8>@pv>#y4m9Nu@3bjm7_16RtM|^l zO8Wf&1K+LJvH3=;(ESKjhMLGlkdWWIq~sz9=I*>s3?vbp4&3h0?Q8cw8vG(G8OWTv z5TUCejM3jww*yfLF}u-|GY_7lVD?Ky>iW0{!k2jMqrl(lC16UWZgoRZbWyX&l?bbK zJDpbN-{!HN@ACLe^GtJ`4(CxS&T$+OCyoUjcNcibIojyzt}@|?0JIO!^K_6H;7*n- zgpmQ>J%k#QX-EcxuwXIMZu|1`GS8jvUfG)9iH4quDsM65Z6{`Zb)G)Xq?<)+gwRZQWr-sab*Ks6w8X2FD|5=Xh^vLr+uEq7(F5p?N&6WE<-UN;wH({@`iSKWc z(73Z_Yst3i(USXvP_oUzjqyH^FNj15yDH^3ar~9@2$B6F3czSDJRk03^c2Udt48Db z`MJI+29}_)r1Vjta`mTpxj6pQErv;Ks);PbBLjY?NQbn9Aa+6nq`;kcbh#A>#0+by z+mZ?anI!h_+^BMj*3stOKqCxjj0Vk=p^10LZ_tfo3^Y@=?)vNr8v>xiu#9kfj^75I zA4x|4gw-EH?;B9}TWEuVl;gKxC>zo(g#4#$1S~l~kw)+*!yFkMzYzlk78|fiv1~;f z+2mm|v?p1WY~k?z0Iy6`F-gJV&60W5?5hDqZ1j>N2V^)|Ey>s+ zHebU}rp9m=o7fS+Z(5Sy5$?rxKvgQ1pxZ-*ADKHWven&I{f<4VXAIUF0TkZ?z0r^g z%A}zogQo`0Zkff)OOhBSON<|=%Xjdm=4T46W6w1tztzwjd2lSkcXfGQ&0zs zD1(ry3MfYdO$f%oKI{alK-NOGC=L0kV)cDk8|TbWimndAz?sjSD5i_xi^+Nsd%5%+ z7TjtOn=i1I$tDxQCQm)`XuLWXRWo!~Ic&9pIeoFjDrn1(Q)wz~SA7qPzE}D;7@x+0 z7%-M&7)=AlQfCAh%?TMI3t_D~=L7U)Xq5bb7ST>*khJ)7V6WrkC#HW9p{}#PO zvAg^P6MXLCjm{+O{q$YMFvq#F(bH}bz|4XrK3fXpC+V+3z(8!KzL^#$nFty<1X&%? zkaUx_i52V99mOjywukP}&zO@3fXss*=V8tmfJytsP-y+I_$ zdpC#)e=QL{1KyMcoBBq|Ih&vTDtPpZBtE#v+!*u1FS@2NMOHFw9RItfi(*@l#LAK$I|%ZH*-rKdeZoEi$`s>t!83!l3*` z+;T+%+)bAvz>GqSNpDpgD)2aT5${xf0`1$hiHMSZ(n0%d^2S(}%nYd+R^l=!YRE$z zKuj3n48hASZ-_Q+9e$n-BGRq}2Q*T_)KArGRl9{wGi2(Xa7h_@07O}!_;}E#v@gzN zRgqN*I9b9trNmy$1~Dq=Mp6yXheR~iAI+~+t|dvg4a>GRBF=D=lasclO~NQrI1Qe* z)hxqW3JI{(5%lKvqG`fI|A_Qu0TqE;Y{R%`{eZQA=726vbycUMc1AnVHmAd({8RrI zOaR7FCWj9Q`P7nrvhjm|ZEE$qO>oXraF7P1B-f>E>5ly1l{LG^x>LoM=$uPpp=+kZG}z;hA`Xg9K$ zPGE{Nrm6U;nQLV-129e>-@)AH6&vPAjug~tgP>tPsHkL`u!>7M0;?zJhQRBPZ)P+2 zRx_@7=n++m=zO}D9}OPhRNvhQWH#Mu={7c+bCua?-XUv~30E13NaIC5X^ z8N>;Bc65!G#yq-%0h}W1_+s^{*6;pt4;No&I)U0zIh^E%DN%1rOe4a0vph#=xT zwTwgie_Jf~j%_!)Y`4X=TV1^Wr`;}}|GxyY5$R|LK-H zfBwWff3OXyW(`T+tsHuoz%@N>)9%%q4X%Ch&kB=6e!mCVY3@U^`;go| zWNRO?y${*RBfFQB3~+2W!S!GgbSa8UP?s3>eL}|MzN3Lv1uP7Gd5>S_!{me+K{SE9 zHq74dN0l>7`TjgTsPuthnsxHmXadXZOi~$I{4R*%V6}4RC*1~o$p5!ny~6n)j%$_Y zf8GRM+yC3i#R54M`Q32<%atL(pE(4`>BtF=0e$6W-0gB-wJA2g88%7p?4V1&_mrh; zI~277=cL3wPU)wizMNB9Vuv>UjMQN+lyZkG{T|d|29$D#jDD)>aPhs>C*QIHpoiu6M2mEEBzQ#VxP&dh8}YyK`9HSPF3$gEw~YVa2EO3@ z-_KY@%H#iK^#5w~PmIV3!v5sjtf@0fK8A;iAgep5)J1)9tp6JC^aFh9LH_J0OL|Pk zTYYS2-wa3-vqhTt^GA>+lu$wmC6rJ?2_=+JLJ1|5P(leMlu$wmCHxWLU!*femH>DF E0Q3