diff --git a/ansible/roles/remnanode/files/node_setup.sh b/ansible/roles/remnanode/files/node_setup.sh new file mode 100644 index 0000000..a4d7ffc --- /dev/null +++ b/ansible/roles/remnanode/files/node_setup.sh @@ -0,0 +1,360 @@ +#!/usr/bin/env bash +set -euo pipefail +export DEBIAN_FRONTEND=noninteractive +export LC_ALL=C + +# ======================== НАСТРОЙКИ ========================== +SSH_PORT=22 # порт SSH +VPN_TCP_PORTS="443" # TCP-порты VPN (через пробел) +VPN_UDP_PORTS="443" # UDP-порты VPN (QUIC) +NODE_PORT="2345" # порт панели / ноды +MY_IP="5.180.253.38" # ВПИШИ СВОЙ IP — crowdsec не забанит +SECRET_KEY="eyJub2RlQ2VydFBlbSI6Ii0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLVxuTUlJQmhqQ0NBU3lnQXdJQkFnSUhBWGMxSkVaWFZqQUtCZ2dxaGtqT1BRUURBakF2TVMwd0t3WURWUVFERXlSclxuV0Zkb2R6UkJOSGxrVlRSdU1qTmxkelpMTlVGWlVFNUJjbEoyVWxONWRpMHhiVmt3SGhjTk1qWXdNekUwTWpFMFxuTVRBMVdoY05Namt3TXpFME1qRTBNVEExV2pBcU1TZ3dKZ1lEVlFRREV4OUJUR2gyVkZGRGRFRXhjRkpDV2tKeFxuV2sxa1JIRTVORmh1VVhsTFFYZ3pNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVNUG84Uzl5SFxuK0F2TEFXalhVZENGYk4xdWlkY0xOTEZUZ0lwVUdBcFZBR0xQZUJhY0RvUWI5RTNPT3lOUHZxOCtwUTcwR0ozSlxubnlZRUlUKytEWHdGazZNNE1EWXdEQVlEVlIwVEFRSC9CQUl3QURBT0JnTlZIUThCQWY4RUJBTUNCYUF3RmdZRFxuVlIwbEFRSC9CQXd3Q2dZSUt3WUJCUVVIQXdFd0NnWUlLb1pJemowRUF3SURTQUF3UlFJaEFKc2Y1YnVzd3FvU1xuQTlMeTJLaEUxaUU3THlQTGVKOWRYbW9FT01VeThGblJBaUFROXJXMFJmWVJpdk1JMGdBVGprZ2V6TU9IbWpaQlxuZ0xMSkxmaCt4T0hIdnc9PVxuLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLSIsIm5vZGVLZXlQZW0iOiItLS0tLUJFR0lOIFBSSVZBVEUgS0VZLS0tLS1cbk1JR0hBZ0VBTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEJHMHdhd0lCQVFRZ044VWVreUtQUEZ2YmQzdDBcbnRUODBMSDNVcS9IU1premU2WG5OclFkYXJzU2hSQU5DQUFRdytqeEwzSWY0QzhzQmFOZFIwSVZzM1c2SjF3czBcbnNWT0FpbFFZQ2xVQVlzOTRGcHdPaEJ2MFRjNDdJMCsrcno2bER2UVluY21mSmdRaFA3NE5mQVdUXG4tLS0tLUVORCBQUklWQVRFIEtFWS0tLS0tIiwiY2FDZXJ0UGVtIjoiLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tXG5NSUlCY1RDQ0FSYWdBd0lCQWdJQkFUQUtCZ2dxaGtqT1BRUURBakF2TVMwd0t3WURWUVFERXlScldGZG9kelJCXG5OSGxrVlRSdU1qTmxkelpMTlVGWlVFNUJjbEoyVWxONWRpMHhiVmt3SGhjTk1qWXdNekEwTVRnd05qTXpXaGNOXG5Nell3TXpBME1UZ3dOak16V2pBdk1TMHdLd1lEVlFRREV5UnJXRmRvZHpSQk5IbGtWVFJ1TWpObGR6WkxOVUZaXG5VRTVCY2xKMlVsTjVkaTB4YlZrd1dUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFUMzVxamh6V1NhXG4vdFJxbDRtQXkwanQ0ZXNEWUo2YkdoMUpoY0pmQisxdWRVV2tBS1dqazBLQVd1WnBNR1ZORjZvblNOVVZ0R1RQXG5GU0NlMTlIVElLOXBveU13SVRBUEJnTlZIUk1CQWY4RUJUQURBUUgvTUE0R0ExVWREd0VCL3dRRUF3SUNoREFLXG5CZ2dxaGtqT1BRUURBZ05KQURCR0FpRUF1QS9UZFVyYlZEVG5ORGJycHJlYm83T0VaNHdpTXVzbVpmWjhqSDFBXG5yWWdDSVFEMHVSSnhPeGNPWnFJRTlXMDJVVHcwcHQwRGJId2U0NWJVc1V6dkhpQ3ZwQT09XG4tLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tIiwiand0UHVibGljS2V5IjoiLS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS1cbk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBMVNLY1ZSR282N01yNXdENGJmQVNcbllCOWdRS0ZsdHg3aFh5dXRpaG13c0x4ZW5vN2xNb1VRWEVqclpJdVNJK1FQU1p6aVQ4b0dlSG1sK2psQWI3SHZcblBNbVN6KzdFdHIwRmVDazhtTENIaGpucG1YSk10ZVY1ZndyZkJwcHdLY1hkMFRzWlhrR0dEcVRMSVA5L29hTjhcblN3UW9reW5iUzNjYUN0LzhPSDJUMWI1anpJYlZXNS9NcFUxY1hIL2cxemdmOW10SGsxYkJSeFA0d1ZYdlVhS0NcblZyWldGalVZZUN2N2hoQjhmNzVRVWJBbERHMEMyaHZxV1h1Tm9Cc0NpVmEvS01RZkh5ZUMvTENaUnd5dWxhemxcblNPQ0pEVU5IUUdoOS9QR0trZ3BGVHFKUS9hbVJpZnZUMDVMclFQLzlsMHZkRTRqNjJOUGF1U1R0UmxWL1NqTGhcbkN3SURBUUFCXG4tLS0tLUVORCBQVUJMSUMgS0VZLS0tLS1cbiJ9" # ВПИШИ SECRET_KEY ноды +# ============================================================= + +RED='\033[0;31m'; GREEN='\033[0;32m'; YEL='\033[1;33m'; NC='\033[0m' +log() { echo -e "${GREEN}[+]${NC} $*"; } +warn() { echo -e "${YEL}[!]${NC} $*"; } +[ "$(id -u)" -eq 0 ] || { echo "Run as root"; exit 1; } +[ -n "$SECRET_KEY" ] || { echo "Впиши SECRET_KEY вверху скрипта"; exit 1; } + +# ============================================================ +# 1. ОБНОВЛЕНИЕ + ПАКЕТЫ +# ============================================================ +log "1/15 System update..." +apt-get update -y && apt-get upgrade -y +apt-get install -y sudo curl wget net-tools socat git jq htop \ + chrony ca-certificates irqbalance zram-tools ufw \ + unattended-upgrades apt-listchanges + +# ============================================================ +# 2. DOCKER +# ============================================================ +log "2/15 Installing Docker..." +curl -fsSL https://get.docker.com | sh + +# ============================================================ +# 3. REMNANODE +# ============================================================ +log "3/15 Setting up remnanode..." +mkdir -p /opt/remnanode +cd /opt/remnanode + +cat > docker-compose.yml << EOF +services: + remnanode: + container_name: remnanode + hostname: remnanode + image: remnawave/node:latest + network_mode: host + restart: always + cap_add: + - NET_ADMIN + volumes: + - /var/log/remnanode:/var/log/remnanode + ulimits: + nofile: + soft: 1048576 + hard: 1048576 + environment: + - NODE_PORT=${NODE_PORT} + - SECRET_KEY="${SECRET_KEY}" +EOF + +mkdir -p /var/log/remnanode +touch /var/log/remnanode/access.log +chmod -R 755 /var/log/remnanode + +docker compose up -d +log "remnanode started" + +# ============================================================ +# 4. CHRONY +# ============================================================ +log "4/15 Chrony..." +systemctl disable --now systemd-timesyncd 2>/dev/null || true +systemctl enable --now chrony +chronyc -a makestep 2>/dev/null || true + +# ============================================================ +# 5. SYSCTL — BBR + ТЮНИНГ ПОД МОБИЛЬНЫЙ VPN +# ============================================================ +log "5/15 Sysctl (BBR + mobile)..." +cat > /etc/sysctl.d/90-vpn-tuning.conf << 'SYSCTL' +# BBR +net.core.default_qdisc = fq +net.ipv4.tcp_congestion_control = bbr + +# TCP fast open (client + server) +net.ipv4.tcp_fastopen = 3 + +# MTU probing (compensate blocked ICMP on path) +net.ipv4.tcp_mtu_probing = 1 + +# CRITICAL for mobile: dont reset cwnd after idle +net.ipv4.tcp_slow_start_after_idle = 0 + +# Reduce bufferbloat (critical for mobile latency) +net.ipv4.tcp_notsent_lowat = 16384 + +# Keepalive (drop dead mobile connections faster) +net.ipv4.tcp_keepalive_time = 300 +net.ipv4.tcp_keepalive_intvl = 30 +net.ipv4.tcp_keepalive_probes = 5 + +# Fast socket recycling +net.ipv4.tcp_fin_timeout = 15 +net.ipv4.tcp_tw_reuse = 1 + +# TCP stack +net.ipv4.tcp_window_scaling = 1 +net.ipv4.tcp_timestamps = 1 +net.ipv4.tcp_sack = 1 +net.ipv4.tcp_ecn = 2 + +# Buffers (balanced for 1-10 Gbit VPS) +net.ipv4.tcp_rmem = 4096 262144 16777216 +net.ipv4.tcp_wmem = 4096 262144 16777216 +net.core.rmem_max = 16777216 +net.core.wmem_max = 16777216 + +# Backlog / queues +net.core.somaxconn = 65535 +net.core.netdev_max_backlog = 16384 +net.core.netdev_budget = 600 +net.core.netdev_budget_usecs = 8000 + +# SYN flood protection +net.ipv4.tcp_syncookies = 1 +net.ipv4.tcp_max_syn_backlog = 8192 + +# OS limits +fs.file-max = 2097152 +net.ipv4.ip_local_port_range = 10240 65535 +SYSCTL + +sysctl --system 2>&1 | grep -v "^$" || true +sysctl net.ipv4.tcp_congestion_control | grep -q bbr && log "BBR active" || warn "BBR unavailable — need kernel 5.4+" + +# ============================================================ +# 6. ЛИМИТЫ ФАЙЛОВЫХ ДЕСКРИПТОРОВ +# ============================================================ +log "6/15 File descriptor limits..." +cat > /etc/security/limits.d/99-nofile.conf << 'FLIM' +* soft nofile 1048576 +* hard nofile 1048576 +root soft nofile 1048576 +root hard nofile 1048576 +FLIM + +mkdir -p /etc/systemd/system.conf.d +cat > /etc/systemd/system.conf.d/99-limits.conf << 'SLIM' +[Manager] +DefaultLimitNOFILE=1048576 +DefaultTasksMax=infinity +SLIM +systemctl daemon-reload + +# ============================================================ +# 7. CROWDSEC +# ============================================================ +log "7/15 CrowdSec..." + +curl -s https://install.crowdsec.net | sh +apt-get install -y crowdsec +apt-get install -y crowdsec-firewall-bouncer-iptables + +cscli console enroll cmmrouhcj000u02jpy3b98fsc + +if [ -n "$MY_IP" ]; then + log " -> Adding ${MY_IP} to CrowdSec whitelist..." + mkdir -p /etc/crowdsec/parsers/s02-enrich + cat > /etc/crowdsec/parsers/s02-enrich/myip-whitelist.yaml << WHITELIST +name: custom/myip-whitelist +description: "Whitelist my personal IP" +whitelist: + reason: "my personal IP" + ip: + - "${MY_IP}" +WHITELIST +fi + +systemctl enable --now crowdsec +systemctl restart crowdsec +systemctl enable --now crowdsec-firewall-bouncer +systemctl restart crowdsec-firewall-bouncer + +log "CrowdSec active" + +# ============================================================ +# 8. УДАЛЕНИЕ ПОЧТЫ +# ============================================================ +log "8/15 Remove mail stack..." +systemctl disable --now postfix sendmail exim4 nullmailer msmtp 2>/dev/null || true +systemctl mask postfix sendmail exim4 nullmailer msmtp 2>/dev/null || true +apt-get purge -y postfix sendmail sendmail-bin sendmail-base \ + exim4 exim4-base exim4-config exim4-daemon-light exim4-daemon-heavy \ + mailutils bsd-mailx s-nail heirloom-mailx msmtp msmtp-mta nullmailer dma ssmtp 2>/dev/null || true +apt-get autoremove -y 2>/dev/null || true +rm -rf /var/spool/mail/* /var/mail/* /etc/postfix /etc/exim4 2>/dev/null || true + +if [ -f /etc/crontab ]; then + grep -qE '^\s*MAILTO=' /etc/crontab \ + && sed -i 's/^\s*MAILTO=.*/MAILTO=""/' /etc/crontab \ + || printf '\nMAILTO=""\n' >> /etc/crontab +fi + +# ============================================================ +# 9. UFW (единственный файрвол, без ручных iptables) +# ============================================================ +log "9/15 UFW firewall..." +ufw --force reset +ufw default deny incoming +ufw default allow outgoing + +# Входящие +ufw allow "${SSH_PORT}/tcp" comment 'SSH' +for p in $VPN_TCP_PORTS; do ufw allow "${p}/tcp" comment 'VPN-TCP'; done +for p in $VPN_UDP_PORTS; do ufw allow "${p}/udp" comment 'VPN-UDP'; done +ufw allow "${NODE_PORT}/tcp" comment 'Panel-Node' +ufw allow 6060/tcp comment 'CrowdSec' + +# Блокировка исходящего абьюза (DROP, не REJECT — REGXA-safe) +ufw deny out to any port 25 proto tcp comment 'Block-SMTP' +ufw deny out to any port 465 proto tcp comment 'Block-SMTPS' +ufw deny out to any port 587 proto tcp comment 'Block-Submission' +ufw deny out to any port 2525 proto tcp comment 'Block-AltSMTP' +ufw deny out to any port 6667 proto tcp comment 'Block-IRC' +ufw deny out to any port 6697 proto tcp comment 'Block-IRC-TLS' +for tp in 9001 9030 9050 9051 9150; do + ufw deny out to any port $tp proto tcp comment 'Block-TOR' +done +ufw deny out to any port 51413 proto tcp comment 'Block-Torrent' +ufw deny out to any port 51413 proto udp comment 'Block-Torrent' + +# ICMP: разрешаем PMTUD (критично для VPN!), блокируем ping +BF="/etc/ufw/before.rules" +if ! grep -q "CUSTOM-ICMP-RULES" "$BF" 2>/dev/null; then + sed -i '/-A ufw-before-input -p icmp --icmp-type echo-request -j ACCEPT/d' "$BF" + sed -i '/^COMMIT/i \ +# === CUSTOM-ICMP-RULES ===\ +-A ufw-before-input -p icmp --icmp-type destination-unreachable -j ACCEPT\ +-A ufw-before-input -p icmp --icmp-type time-exceeded -j ACCEPT\ +-A ufw-before-input -p icmp --icmp-type parameter-problem -j ACCEPT\ +-A ufw-before-input -p icmp --icmp-type echo-request -j DROP\ +# === END CUSTOM-ICMP-RULES ===' "$BF" +fi + +ufw --force enable +log "UFW active" + +# ============================================================ +# 10. JOURNALD +# ============================================================ +log "10/15 Journald..." +mkdir -p /etc/systemd/journald.conf.d +cat > /etc/systemd/journald.conf.d/override.conf << 'JRNL' +[Journal] +SystemMaxUse=200M +RuntimeMaxUse=200M +Compress=yes +Storage=auto +JRNL +systemctl restart systemd-journald + +# ============================================================ +# 11. ZRAM +# ============================================================ +log "11/15 Zram..." +modprobe zram 2>/dev/null || { + apt-get install -y "linux-modules-extra-$(uname -r)" 2>/dev/null || true + modprobe zram 2>/dev/null || warn "zram unavailable" +} +cat > /etc/default/zramswap << 'ZRM' +ALGO=lz4 +PERCENTAGE=50 +PRIORITY=100 +ZRM +systemctl enable --now zramswap 2>/dev/null || true + +# ============================================================ +# 12. IRQBALANCE +# ============================================================ +log "12/15 Irqbalance..." +systemctl enable --now irqbalance + +# ============================================================ +# 13. АВТООБНОВЛЕНИЯ БЕЗОПАСНОСТИ +# ============================================================ +log "13/15 Security auto-updates..." +cat > /etc/apt/apt.conf.d/20auto-upgrades << 'AUTOUP' +APT::Periodic::Update-Package-Lists "1"; +APT::Periodic::Unattended-Upgrade "1"; +APT::Periodic::AutocleanInterval "7"; +AUTOUP + +# ============================================================ +# 14. OVERRIDE ДЛЯ XRAY / SING-BOX +# ============================================================ +log "14/15 Xray/sing-box override..." +for SVC in xray xray-core sing-box; do + if systemctl list-unit-files 2>/dev/null | grep -q "^${SVC}.service"; then + log " -> override for ${SVC}" + mkdir -p "/etc/systemd/system/${SVC}.service.d" + cat > "/etc/systemd/system/${SVC}.service.d/override.conf" << XOVER +[Service] +LimitNOFILE=1048576 +LimitNPROC=infinity +Restart=always +RestartSec=3s +XOVER + systemctl daemon-reload + systemctl restart "${SVC}" 2>/dev/null || true + fi +done + +# ============================================================ +# 15. SSH HARDENING +# ============================================================ +log "15/15 SSH hardening..." +SC="/etc/ssh/sshd_config" +[ -s /root/.ssh/authorized_keys ] && \ + sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin prohibit-password/' "$SC" +sed -i 's/^#\?MaxAuthTries.*/MaxAuthTries 3/' "$SC" +sed -i 's/^#\?ClientAliveInterval.*/ClientAliveInterval 120/' "$SC" +sed -i 's/^#\?ClientAliveCountMax.*/ClientAliveCountMax 3/' "$SC" +systemctl reload sshd 2>/dev/null || systemctl reload ssh 2>/dev/null || true + +# ============================================================ +# ФИНАЛ +# ============================================================ +echo "" +echo "==========================================" +echo -e "${GREEN} SETUP COMPLETE${NC}" +echo "==========================================" +echo "" +echo "--- remnanode ---" +docker ps | grep remnanode || true +echo "" +echo "--- BBR ---" +sysctl net.ipv4.tcp_congestion_control +sysctl net.core.default_qdisc +echo "" +echo "--- UFW ---" +ufw status numbered +echo "" +echo "--- CrowdSec ---" +cscli version 2>/dev/null || true +cscli machines list 2>/dev/null || true +echo "" +echo "--- SMTP check ---" +ss -lntp | grep -E ':(25|465|587)\b' || echo " [OK] No SMTP listeners" +echo "" +echo "--- zram ---" +swapon --show 2>/dev/null || true +echo "" +echo "==========================================" +echo -e "${YEL}ПОСЛЕ ЗАПУСКА:${NC}" +echo " 1. Подтверди enroll в консоли: https://app.crowdsec.net" +echo " 2. reboot" +echo "==========================================" diff --git a/ansible/roles/remnanode/tasks/main.yml b/ansible/roles/remnanode/tasks/main.yml new file mode 100644 index 0000000..acd13c3 --- /dev/null +++ b/ansible/roles/remnanode/tasks/main.yml @@ -0,0 +1,29 @@ +--- +- name: Copy node setup script + copy: + src: node_setup.sh + dest: /root/node_setup.sh + mode: '0700' + +- name: Fill SECRET_KEY in script + lineinfile: + path: /root/node_setup.sh + regexp: '^SECRET_KEY=""' + line: 'SECRET_KEY="{{ node_secret_key }}"' + +- name: Fill MY_IP in script + lineinfile: + path: /root/node_setup.sh + regexp: '^MY_IP=".*"' + line: 'MY_IP="{{ node_my_ip }}"' + +- name: Fill CrowdSec enroll key + lineinfile: + path: /root/node_setup.sh + regexp: '^cscli console enroll.*' + line: 'cscli console enroll {{ node_crowdsec_enroll }}' + +- name: Run node setup script + shell: /root/node_setup.sh + args: + creates: /opt/remnanode/docker-compose.yml diff --git a/ansible/roles/remnanode/vars/main.yml b/ansible/roles/remnanode/vars/main.yml new file mode 100644 index 0000000..e2a549f --- /dev/null +++ b/ansible/roles/remnanode/vars/main.yml @@ -0,0 +1,5 @@ +--- +node_ssh_port: 22 +node_port: 2345 +node_vpn_tcp_ports: "443" +node_vpn_udp_ports: "443" diff --git a/ansible/roles/remnanode/vars/secrets.yml b/ansible/roles/remnanode/vars/secrets.yml new file mode 100644 index 0000000..2704408 --- /dev/null +++ b/ansible/roles/remnanode/vars/secrets.yml @@ -0,0 +1,139 @@ +$ANSIBLE_VAULT;1.1;AES256 +65333465393161356437353463313930373538373631306664373039303565393930373430613762 +3265383737363866636634373164306434373939303534320a636434623061613639326535373863 +65343661623439646137343264646330633339356335633538623739613034303932396530356133 +3534636465666565650a396636623935393862313865613034376363393237326132396530653036 +30383639633033376333343231343663303832666564616237313732326565653566326262326235 +36336633653637356530343238613136363533373666393761383934646533663338636535386139 +36356139363765653266393236626563653061646536363562373061313336396639386139393137 +31366539646562326239626535356235663836613863316666373733303330356332663533316134 +37353762646566656332333733336338633234313935373438626264343561343032303834333736 +64306432326332383463393465363439643533383037653033613363323938326331383064323236 +39366361336634393266616339643864323261633738636165366363303735653934376633653566 +61653834343732363534333431346566396166616233303430643538346636623161376263343339 +66323838323936653839343938383131323830393131623462336263356664333933346633646230 +33373336356664393734383333393565333966643066363463636333613838356537643564626638 +36633631376265393336383966343033656263333164356332363732356534333932336631393231 +34616566363933353438613564313965313461366263646232373239323364396564653035373732 +32653135323961663436323237376662353731336164343638663738373464343764343135643834 +38656438323664316365613264626363323431303138623935306462623032303035613761333738 +61346438623163353463336363356264616230616230326632656638343932363666643363636462 +37636566653763653536626465613062366164653637653866393639326663646236663965653764 +63336339623463303162303961306135303632353736333835643336663365636665363535303938 +34316636383132633365336462316461643634313832636330616231303030333437363135303834 +62336663663532623237633438356564303165316231636337646639343833306331366634616564 +37393962636638666130303339323839336637346265356637616236323935373739333938373066 +62633562313661383162666432633830343430616134353036613631303462393834666666656238 +38353439663430316533623632363061316337633265383263373235356562663231363730303561 +35356233613339633331663537666664396235656536613838316338376333323233336364616135 +32333832333663656333316133333334643265663439393266623664366565336361613430396265 +62373964363962346562646431376466363738333933626262663766356437326536616461633430 +65396633393361656139626161613939313433326665383833386332353538636462363966323963 +61643865373832666433623834663361356161386336616336623932316532613566353837326139 +37356336323231623130313434356461326231663130353464366366383262376636323162333432 +66376261626263623366613062396437623735346630633530313837626539643538306665623061 +35303636383731653533323932323135646633373164323039643862626334663032376461666330 +32323931633330653539353339323535333432616237323165633531646465656132626231613365 +61663964656362333835303238326664333762653839373138363166313161383534653632353864 +65646236666234623665663737363962613835323538373361653531323237393136613332613833 +30623562383632326631633338363964613539623061333230383335643266343339633931643030 +39643733366136646339336133623639623234303365366436333330666263396338383864313532 +38653665326163336164666636653964306362653931346631643837313061323063313535386266 +37333435636466306164303362326162653839353637366130633639306630346465326266373530 +39613238636337333761666463643136303433663232333937316330633833393436313166333464 +32316336636636633562616637646633313866386537313464333462336232636539626237636534 +39326565346638376437343134633437353432386261663631356162333961636331626463386334 +39343663386438653735343533646536343364626465363836633732313462393061373833643631 +36326464373238303562313634303761316638623030353661656563643132303138613934356334 +39653066643936613766626463393730336632613566343366663435653162653465663437653138 +39663165356236623730623738343632373765653937656535343262656530393330323130346130 +63306361323535376136333938333266613362373036353737336437646461373861393931383635 +63353762343465326261356630323262316136343266386435303737343663353832323464383232 +36373036393230386331333238623935316238613761316262373839626534386463316235623438 +35663830303734623961656363333033306533656133383261306566366636653264323361313239 +63346361336164656262316264616231613462643430616662653831313930643761663034663538 +31303032396238636265616563306536613738343261313336383865643861613335353431363038 +34656561616466373662343563306538386663303231343038323939316565333163633132353632 +34316439613037303532386634633134323662323866346163383666656338633439343936346434 +33333430323439656431383066373934373065393866363564346665666462383839636533626530 +36353533663938313733643164336332303839633931363433616630653834303530366139396537 +38643339326366363732656262653333303962656434316132626666343963626238323361323839 +39653538646536653537643934343237383738303339386339303736313838313864313561313330 +37343462373665303237663766373831333463626230326133316631303031396461633137363331 +38653637353530383530666364343132353163666462313664653265333830323765373434346331 +66613065373562313737653431316637336331313736303666616331313837636664623139316335 +35663261663665326261333266663334396535313262656333633639363936653639626632383034 +36643131353361353537346636323866663864626665636532623433333961633730363263373635 +38663062366635646430323739313737626235363034326635613366346633626461393037346632 +31313036353762363965313534333532643838643333653135303265343439376363323234653731 +35316239333136303431333034383336363662653732376665303435363130326633303266333137 +33333338376532623962333134633231336464646264623566666631356365623339396332303731 +34623531393534313462653935303939303838326666376335363838363363666639373466666161 +63653466323034663161613135656563623831393738313136383331363663323238316265383363 +32396463353734646232366237396532653461666562643534356431303134386136653061373561 +31393666613336313134356264666435636562626263643335616234393062306433323064653562 +39643462643531313866326130613535353139653461336634613235376365373338316637333731 +33663131313463323030633136613963316237626235376639393130343838646438646337646538 +33383430363334356434616336373665363930623937626138393936643536646261306363303230 +38663235666531306466356335366562383834666630653431353039616662363631343336313730 +38653238393464313566343430613162616638633363646361356465626165623464333164356136 +39343761643332323165336634323130626165396135323336363064373835616539623437653163 +34386564393266613463663632633634646536343436343038663561383432306539353338343539 +61336363373237663065376632376130623262643632663138306262613930386638323931656464 +65616461306638313163656133643734316561323231313433306533356364643861306633373663 +34623638633663316436633134626134613566343534636264303465363238303037623632653432 +35303634363636643834386330303435373232373365313137346630626661393038373135613964 +62356635633130643161313735646531383465336364653565303861616363303439646664346135 +38366363666234666366323135663530346334303664313565336163383735316332346338336439 +66343665313032613234363230356566613062323436633533343438353239306432646562643334 +64383336616566663262303338366631383530356561313235303934613432383238383533326363 +35633433613737383537373437303863373236616335386435336333396533666662323134643632 +32316235373535643938633361666635346533613330336636393432373331653164656537663163 +36626535646563633365373961666165313234666661313761653861366635396134646139303162 +66313830316563366137383339346661623935643239316462313166363131363065626237643038 +61336433663635663037343539363965333430613038303830393464626639303637633863356530 +65316234333763646534303332653263626364386138666134353231383530383631623432393531 +63373562323231303137633034353130653834356463666133386537376132656239623337326232 +61613264323339323538306564383266306365666462663435363331396261346666336663643665 +65373361666130363162316635393536666539613539653362393932616562376536363739643633 +63323638383239356365303262363035326163646134643763313830396234336635393561643337 +30356662343930663338393337336165396664366635386664623338316235613835346330633333 +34353365386132376163306531653064376333366436363561336539663363383233343832343432 +36613761373538653339383133646131386333323339336437633636653862623535656330393532 +65366561643432663565353239336536376635356534613935633532366264333038653030653265 +65323138386362623038656130656262393765623035306661383766646234623064636262613062 +38616664333634643964346262636336656533343033633730616539343336666538386230376536 +63326362323338323763376538353532303134383431373939383230633463356234333861356238 +66633232306634353833303237343265396230613439396662633861656637663735393164333633 +34373862373130366431623436383039306531656265626461643962326363333537366333306263 +38333831373264363134323931643263323839393530666364633539373539303033316432643962 +65663265653864326337373263313531346434663838653932613936373032666431373266636436 +34353638383436613437346661656536363639623931363965396139353135663766393166333738 +63643535353861373031613861323266313036643332626234323036396362306633316131646631 +65623939303764643235383965363535393464656536393633386536346532373262343335663436 +34303839386262616562383433656538633736613864336162633766303833623863653063306438 +63373263353738363166396231656465646437616531323363663561636137663265363238333132 +31666462623964303465323235343232396233336466346233346233616264303037356439376564 +39633636323365653030333438613766653435306330373637653562386437643036353534393633 +37333363363836333235653038373665623063646232643931323164666230343630323335303839 +62393562363739663032346236623839396231366238643365306232613762326464313131303561 +36363935396435396464623331326432323261613865373138323932636263386631323165303337 +61656461373833303630666335396530333964663930363263653331613666373663363038393261 +37616264643538346139343864646562346131376531343134306463613664316362633038613434 +38346264653637366134376433333136666533353763336261633533353865623230623937616662 +30316137316535356630383034343036326561383230326135653561333262393765646566303963 +62636235383766643262303333316265363862356633313730653034306637366435623265383839 +35663337333264613936613338623939336561663163323863336337336537323766336561373766 +37363934646337623964326561656235316161613365623163303830306163316635383362383335 +39383933616663306438396135613230363033306338636537313661303163313136646234366130 +65323239643632363761313764326134303035313431663137643737626334613935656661303437 +30356437656664656135623730353465393134353264393939653732623065623133323030356161 +33626233666536356539326662663736303835653261396634666433666563366364363863356166 +61623966373530386636376361643537356266666532613836316563313339363763383266326561 +33346135356639663938343030646237636331653739613332316333366631616563646462653662 +34353533393539313461643639386334353532353630666239376337376238623462643839646537 +63623161306539653237316335303531306566376231323339393237396431303334363130656261 +64386636353137653664363937663461393436326436633136646666613962393835623433343335 +35396637336566653137373537323735356436343762386330313433393538613533643665396530 +61333034383836626364383038646639333838383138343832636230636365313365323862386265 +6563346336616638386331306664646462383030366236663230