diff --git a/m-labs-intl/60-tunnels.yaml b/m-labs-intl/60-tunnels.yaml new file mode 100644 index 00000000..ce8594e7 --- /dev/null +++ b/m-labs-intl/60-tunnels.yaml @@ -0,0 +1,18 @@ +network: + version: 2 + renderer: networkd + ethernets: + eth0: + addresses: + - 5.78.86.156/32 + - 2a01:4ff:1f0:83de::2/64 + - 2a01:4ff:1f0:83de::3/64 + - 2a01:4ff:1f0:83de::4/64 + tunnels: + gre1: + mode: gre + local: 5.78.86.156 + remote: 94.190.212.123 + addresses: + - 10.47.3.0/31 + diff --git a/m-labs-intl/gretun.service b/m-labs-intl/gretun.service new file mode 100644 index 00000000..0576dc2f --- /dev/null +++ b/m-labs-intl/gretun.service @@ -0,0 +1,14 @@ +[Unit] +Description=GRE tunnel to the main host +After=network.target + +[Service] +Type=simple +User=root +ExecStart=/root/gretun.sh +ExecStop=/root/gretun_down.sh +Restart=on-failure +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/m-labs-intl/gretun.sh b/m-labs-intl/gretun.sh new file mode 100755 index 00000000..8bb08828 --- /dev/null +++ b/m-labs-intl/gretun.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +/usr/sbin/iptables -t nat -A PREROUTING -p tcp -i eth0 --dport 25 -j DNAT --to-destination 10.47.3.1:25 +/usr/sbin/iptables -A FORWARD -p tcp -d 10.47.3.1/31 --dport 25 -j ACCEPT + +/usr/sbin/iptables -t nat -A PREROUTING -p tcp -i eth0 --dport 587 -j DNAT --to-destination 10.47.3.1:587 +/usr/sbin/iptables -A FORWARD -p tcp -d 10.47.3.1/31 --dport 587 -j ACCEPT + +/usr/sbin/iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT +/usr/sbin/iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE diff --git a/m-labs-intl/gretun_down.sh b/m-labs-intl/gretun_down.sh new file mode 100755 index 00000000..b968a12b --- /dev/null +++ b/m-labs-intl/gretun_down.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +/usr/sbin/iptables -t nat -D PREROUTING -p tcp -i eth0 --dport 25 -j DNAT --to-destination 10.47.3.1:25 +/usr/sbin/iptables -D FORWARD -p tcp -d 10.47.3.1/31 --dport 25 -j ACCEPT + +/usr/sbin/iptables -t nat -D PREROUTING -p tcp -i eth0 --dport 587 -j DNAT --to-destination 10.47.3.1:587 +/usr/sbin/iptables -D FORWARD -p tcp -d 10.47.3.1/31 --dport 587 -j ACCEPT + +/usr/sbin/iptables -D FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT +/usr/sbin/iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE diff --git a/m-labs-intl/m-labs-intl.com b/m-labs-intl/m-labs-intl.com new file mode 100644 index 00000000..7e76e8c2 --- /dev/null +++ b/m-labs-intl/m-labs-intl.com @@ -0,0 +1,81 @@ +upstream rfq_server { + server 127.0.0.1:5000; +} + +server { + limit_conn addr 5; + + root /var/www/m-labs-intl.com/html; + index index.html index.htm index.nginx-debian.html; + + server_name m-labs-intl.com; + + location / { + try_files $uri $uri/ =404; + } + + listen [::]:443 ssl ipv6only=on; # managed by Certbot + listen 443 ssl; # managed by Certbot + ssl_certificate /etc/letsencrypt/live/m-labs-intl.com/fullchain.pem; # managed by Certbot + ssl_certificate_key /etc/letsencrypt/live/m-labs-intl.com/privkey.pem; # managed by Certbot + include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot + ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot +} + +server { + server_name www.m-labs-intl.com; + return 301 https://m-labs-intl.com$request_uri; + + listen [::]:443 ssl; # managed by Certbot + listen 443 ssl; # managed by Certbot + ssl_certificate /etc/letsencrypt/live/m-labs-intl.com/fullchain.pem; # managed by Certbot + ssl_certificate_key /etc/letsencrypt/live/m-labs-intl.com/privkey.pem; # managed by Certbot + include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot + ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot +} + +server { + server_name hooks.m-labs-intl.com; + limit_conn addr 5; + + location /rfq { + proxy_pass http://rfq_server/rfq; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_read_timeout 30; + proxy_connect_timeout 30; + proxy_send_timeout 30; + } + + location / { + return 418; + } + + listen [::]:443 ssl; # managed by Certbot + listen 443 ssl; # managed by Certbot + ssl_certificate /etc/letsencrypt/live/m-labs-intl.com/fullchain.pem; # managed by Certbot + ssl_certificate_key /etc/letsencrypt/live/m-labs-intl.com/privkey.pem; # managed by Certbot + include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot + ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot +} + +server { + limit_conn addr 5; + if ($host = m-labs-intl.com) { + return 301 https://$host$request_uri; + } # managed by Certbot + + + if ($host = www.m-labs-intl.com) { + return 301 https://m-labs-intl.com$request_uri; + } # managed by Certbot + + + listen 80; + listen [::]:80; + + server_name m-labs-intl.com www.m-labs-intl.com hooks.m-labs-intl.com; + return 301 https://$host$request_uri; +} \ No newline at end of file diff --git a/m-labs-intl/m-labs.hk.conf b/m-labs-intl/m-labs.hk.conf new file mode 100644 index 00000000..ba2a34a6 --- /dev/null +++ b/m-labs-intl/m-labs.hk.conf @@ -0,0 +1,34 @@ + + +connections { + m_labs { + version = 2 + encap = no + mobike = no + send_certreq = no + proposals = aes128gcm128-sha256-prfsha256-curve25519,aes128gcm128-sha256-prfsha256-ecp256 + local_addrs = 5.78.86.156 + remote_addrs = 94.190.212.123 + local { + auth = pubkey + id = fqdn:m-labs-intl.com + pubkeys = m-labs-intl.com + } + remote { + auth = pubkey + id = fqdn:m-labs.hk + pubkeys = m-labs.hk + } + children { + con1 { + mode = transport + ah_proposals = sha256-curve25519,sha256-ecp256 + esp_proposals = + local_ts = 5.78.86.156[gre] + remote_ts = 94.190.212.123[gre] + start_action = start + close_action = none + } + } + } +} \ No newline at end of file diff --git a/m-labs-intl/mail.secret b/m-labs-intl/mail.secret new file mode 100644 index 00000000..e69de29b diff --git a/m-labs-intl/nginx.conf b/m-labs-intl/nginx.conf new file mode 100644 index 00000000..9e0d8b81 --- /dev/null +++ b/m-labs-intl/nginx.conf @@ -0,0 +1,65 @@ +user www-data; +worker_processes auto; +pid /run/nginx.pid; +error_log /var/log/nginx/error.log; +include /etc/nginx/modules-enabled/*.conf; + +events { + worker_connections 768; + # multi_accept on; +} + +http { + + ## + # Basic Settings + ## + + sendfile on; + tcp_nopush on; + types_hash_max_size 2048; + # server_tokens off; + + server_names_hash_bucket_size 64; + # server_name_in_redirect off; + + include /etc/nginx/mime.types; + default_type application/octet-stream; + + ## + # SSL Settings + ## + + ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE + ssl_prefer_server_ciphers on; + + # Rate limiting + limit_conn_zone $binary_remote_addr zone=addr:10m; + + ## + # Logging Settings + ## + + access_log /var/log/nginx/access.log; + + ## + # Gzip Settings + ## + + gzip on; + + # gzip_vary on; + # gzip_proxied any; + # gzip_comp_level 6; + # gzip_buffers 16 8k; + # gzip_http_version 1.1; + gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; + + ## + # Virtual Host Configs + ## + + include /etc/nginx/conf.d/*.conf; + include /etc/nginx/sites-enabled/*; +} + diff --git a/m-labs-intl/rfq.service b/m-labs-intl/rfq.service new file mode 100644 index 00000000..79b6858d --- /dev/null +++ b/m-labs-intl/rfq.service @@ -0,0 +1,12 @@ +[Unit] +Description=RFQ service +After=network.target + +[Service] +Type=simple +User=rfqserver +ExecStart=/home/rfqserver/runrfq.sh +Restart=on-failure + +[Install] +WantedBy=multi-user.target diff --git a/m-labs-intl/runrfq.sh b/m-labs-intl/runrfq.sh new file mode 100644 index 00000000..c728d389 --- /dev/null +++ b/m-labs-intl/runrfq.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +export FLASK_DEBUG=0 +export FLASK_MAIL_SERVER=mail.m-labs.hk +export FLASK_MAIL_PORT=465 +export FLASK_MAIL_USE_SSL=True +export FLASK_MAIL_USERNAME=sysop-intl@m-labs-intl.com +export FLASK_MAIL_PASSWORD_FILE=/home/rfqserver/mail.secret +export FLASK_MAIL_RECIPIENT=sales@m-labs.hk +export FLASK_MAIL_SENDER=sysop-intl@m-labs-intl.com + +cd /home/rfqserver/web2019/server +source venv/bin/activate +python3 -m flask --app rfq run --port=5000 \ No newline at end of file diff --git a/m-labs-intl/setup.md b/m-labs-intl/setup.md new file mode 100644 index 00000000..7923aa1a --- /dev/null +++ b/m-labs-intl/setup.md @@ -0,0 +1,99 @@ +# Setup m-labs-intl.com server + +```shell +# Install required packages +apt install git nginx-full python3 python3.12-venv python3-pip iptables ufw \ + strongswan strongswan-swanctl strongswan-pki strongswan-libcharon +snap install --classic certbot +ln -s /snap/bin/certbot /usr/bin/certbot + +# Set up networks (includes GRE) +cp 60-tunnels.yaml /etc/netplan/ +netplan apply + +# set up IPsec-AH connection +cp m-labs.hk.conf /etc/swanctl/conf.d/ +echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.conf +sysctl -p +cp m-labs.hk /etc/swanctl/pubkey/m-labs.hk # get pubkey from nixbld +pki --gen --type rsa --size 4096 --outform pem > /etc/swanctl/private/m-labs-intl.com +pki --pub --in /etc/swanctl/private/m-labs-intl.com --outform pem > /etc/swanctl/pubkey/m-labs-intl.com +cp /etc/swanctl/pubkey/m-labs-intl.com m-labs-intl.com # add it to the nixbld +systemctl enable strongswan --now +systemctl restart strongswan + +# Set up website +cp m-labs-intl.com /etc/nginx/sites-available/ +cp nginx.conf /etc/nginx/ +ln -s /etc/nginx/sites-available/m-labs-intl.com /etc/nginx/sites-enabled/ +systemctl enable nginx --now +service nginx restart + +# Issue SSL certificate - website only, the mail is on the HK side +certbot --nginx +service nginx restart + +# Create a user for automatic website deployment from nixbld +useradd -m zolaupd +mkdir -p /var/www/m-labs-intl.com/html +chown -R zolaupd /var/www/m-labs-intl.com/ +sudo -u zolaupd sh -c ' + cd /home/zolaupd; + mkdir /home/zolaupd/.ssh; + echo -n "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIP1OJJM8g/1ffxDjN31XKEfGmrYaW03lwpyTa1UGWqVx + ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIF6R6XK0IiuAKxVKvSABm4m9bfOlvfJcMvTpjenuXUPv" > /home/zolaupd/.ssh/authorized_keys + chmod 700 .ssh/ + chmod 600 .ssh/authorized_keys + ' + +# Create a user for RFQ hooks service +useradd -m rfqserver +cp runrfq.sh /home/rfqserver/ +cp mail.secret /home/rfqserver/ +chown rfqserver /home/rfqserver/runrfq.sh +chmod +x /home/rfqserver/runrfq.sh +chown rfqserver /home/rfqserver/mail.secret + +sudo -u rfqserver sh -c ' + cd /home/rfqserver; + git clone https://git.m-labs.hk/M-Labs/web2019.git; + cd web2019; + python3 -m venv ./venv; + source venv/bin/activate; + pip install -r requirements.txt; +' +cp rfq.service /etc/systemd/system/ + +# Automate port forwarding rules creation +cp gretun.sh /root/gretun.sh +cp gretun_down.sh /root/gretun_down.sh +chmod u+x /root/gretun.sh +chmod u+x /root/gretun_down.sh +cp gretun.service /etc/systemd/system/ + +# Enable custom services +systemctl daemon-reload +systemctl enable rfq.service --now +systemctl enable gretun.service --now + +# Setup basic firewall rules +ufw default deny +ufw default allow outgoing + +ufw allow from 94.190.212.123 +ufw allow from 2001:470:f891:1::/64 +ufw allow from 202.77.7.238 +ufw allow from 2001:470:18:390::2 +ufw allow "Nginx HTTP" +ufw allow "Nginx HTTPS" +ufw limit OpenSSH +ufw allow 25/tcp +ufw allow 587/tcp +ufw limit 500,4500/udp + +ufw route allow in on gre1 out on eth0 +ufw allow from 10.47.3.0/31 + +ufw show added +ufw enable +``` \ No newline at end of file