Secure Ubuntu server bằng VPN WireGuard: giới hạn SSH chỉ qua mạng riêng
SSH mở ra Internet → tiện nhưng rủi ro. Bot quét port 22 liên tục, brute-force, dò user, thử key yếu, khai thác CVE mới. Dù bạn dùng key auth, tắt password, đổi port SSH, bật Fail2ban… bề mặt tấn công vẫn còn.
Giải pháp mạnh hơn: không public SSH. Chỉ cho SSH chạy qua mạng riêng WireGuard VPN. Internet không thấy SSH. Muốn quản trị server → phải kết nối VPN trước.
Mô hình:
– Server Ubuntu public IP.
– WireGuard tạo interface riêng: wg0.
– Server VPN IP: 10.8.0.1.
– Laptop/admin VPN IP: 10.8.0.2.
– SSH chỉ listen trên 10.8.0.1 hoặc firewall chỉ cho SSH từ 10.8.0.0/24.
– Port WireGuard UDP 51820 mở ra Internet.
– Port SSH 22 đóng với Internet.
Kết quả: attacker scan public IP → không thấy SSH. Admin có VPN key → vào được.
Vì sao nên đặt SSH sau WireGuard?
Giảm bề mặt tấn công
SSH public → ai cũng thử kết nối được. Dù không login được, daemon vẫn nhận traffic.
SSH qua WireGuard → chỉ peer có private key hợp lệ mới vào mạng VPN. Không có key → packet bị bỏ.
Public SSH → bị quét. SSH private → gần như “biến mất”.Bảo mật nhiều lớp
Bạn có 2 lớp:
1. WireGuard key để vào mạng riêng. 2. SSH key để đăng nhập server.
Mất 1 key chưa đủ. Attacker cần cả VPN private key + SSH private key + user hợp lệ.
Quản trị sạch hơn
Có nhiều server? Gán mỗi server 1 IP VPN:
– 10.8.0.1 → bastion/server chính
– 10.8.0.10 → app server
– 10.8.0.20 → DB server
Sau đó SSH nội bộ:
Không cần expose SSH từng máy.
Chuẩn bị
Ví dụ dùng Ubuntu 22.04/24.04.
Cần:
– 1 Ubuntu server có public IP.
– Quyền root hoặc user sudo.
– 1 client: laptop Linux/macOS/Windows.
– Đã có SSH hiện tại để cấu hình ban đầu.
Cài WireGuard trên Ubuntu server
Cập nhật pkg:
sudo apt update
sudo apt install -y wireguardTạo key:
wg genkey | sudo tee /etc/wireguard/server_private.key | wg pubkey | sudo tee /etc/wireguard/server_public.key
sudo chmod 600 /etc/wireguard/server_private.keyXem key:
sudo cat /etc/wireguard/server_private.key
sudo cat /etc/wireguard/server_public.keyTạo config server:
sudo nano /etc/wireguard/wg0.confNội dung mẫu:
[Interface]
Address = 10.8.0.1/24
ListenPort = 51820
PrivateKey = SERVER_PRIVATE_KEY
SaveConfig = false
[Peer]
PublicKey = CLIENT_PUBLIC_KEY
AllowedIPs = 10.8.0.2/32
Thay:
– SERVER_PRIVATE_KEY → nội dung /etc/wireguard/server_private.key
– CLIENT_PUBLIC_KEY → tạo ở client, bước sau.
Tạo key client
Trên Linux/macOS client:
wg genkey | tee client_private.key | wg pubkey > client_public.key
cat client_private.key
cat client_public.keyTrên Windows: dùng app WireGuard → Add Tunnel → Empty tunnel → app tự tạo key.
Config client:
[Interface]
Address = 10.8.0.2/32
PrivateKey = CLIENT_PRIVATE_KEY
DNS = 1.1.1.1
[Peer]
PublicKey = SERVER_PUBLIC_KEY
Endpoint = SERVER_PUBLIC_IP:51820
AllowedIPs = 10.8.0.0/24
PersistentKeepalive = 25
Giải thích nhanh:
– Address → IP VPN client.
– Endpoint → public IP server + port WireGuard.
– AllowedIPs = 10.8.0.0/24 → chỉ route mạng VPN qua tunnel, không route toàn bộ Internet.
– PersistentKeepalive = 25 → hữu ích nếu client sau NAT.
Bật WireGuard server
Trên server:
sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0
sudo systemctl status wg-quick@wg0Kiểm tra:
sudo wg
ip addr show wg0Mở UDP port 51820 trên firewall/cloud firewall.
Nếu dùng UFW:
sudo ufw allow 51820/udpNếu cloud provider có security group/firewall riêng, mở thêm UDP 51820.
Test kết nối VPN
Bật tunnel client. Từ client:
ping 10.8.0.1Nếu ping OK, thử SSH qua VPN:
Nếu login OK → WireGuard + SSH hoạt động.
Nếu không ping được:
– Kiểm tra sudo wg trên server có handshake chưa.
– Kiểm tra public IP/port đúng chưa.
– Kiểm tra UDP 51820 được mở chưa.
– Kiểm tra key peer đúng chưa.
– Kiểm tra AllowedIPs không trùng sai.
Cách 1: Giới hạn SSH bằng firewall UFW
Đây là cách dễ, ít rủi ro. SSH vẫn listen mọi interface, nhưng firewall chỉ cho VPN subnet vào.
Cho phép SSH từ VPN:
sudo ufw allow from 10.8.0.0/24 to any port 22 proto tcpTừ chối SSH public:
sudo ufw deny 22/tcpBảo đảm WireGuard vẫn mở:
sudo ufw allow 51820/udpBật UFW nếu chưa bật:
sudo ufw enable
sudo ufw status verboseThứ tự rule UFW có thể ảnh hưởng. Kiểm tra:
sudo ufw status numberedBạn muốn thấy logic:
– Allow 51820/udp từ anywhere.
– Allow 22/tcp từ 10.8.0.0/24.
– Deny 22/tcp từ anywhere.
Test từ client VPN:
Test từ ngoài VPN:
ssh user@SERVER_PUBLIC_IPKỳ vọng: qua VPN OK, public IP bị timeout/refused.
Cách 2: Cho SSH chỉ listen trên IP WireGuard
Cách này gọn hơn: SSH daemon chỉ bind vào 10.8.0.1, không bind public IP.
Mở file:
sudo nano /etc/ssh/sshd_configThêm/sửa:
ListenAddress 10.8.0.1Kiểm tra config:
sudo sshd -tRestart SSH:
sudo systemctl restart sshKiểm tra socket:
ss -tlnp | grep sshKỳ vọng:
LISTEN 0 128 10.8.0.1:22 ...Không nên thấy:
0.0.0.0:2210.8.0.1 chưa tồn tại → SSH có thể fail bind. Khắc phục bằng systemd dependency hoặc dùng firewall thay vì bind IP. Với hầu hết case, UFW allow/deny đơn giản hơn, an toàn hơn.
Hardening SSH bổ sung
Dù SSH đã nằm sau VPN, vẫn nên harden.
Mở:
sudo nano /etc/ssh/sshd_configKhuyến nghị:
PasswordAuthentication no
PermitRootLogin no
PubkeyAuthentication yes
KbdInteractiveAuthentication no
X11Forwarding no
AllowUsers youruserTest config:
sudo sshd -t
sudo systemctl reload sshÝ nghĩa:
– PasswordAuthentication no → chặn brute-force password.
– PermitRootLogin no → tránh login root trực tiếp.
– AllowUsers → chỉ user cụ thể được SSH.
– reload thay vì restart → ít gián đoạn hơn.
Quản lý nhiều admin
Mỗi admin nên có peer riêng. Không dùng chung key.
Ví dụ thêm admin 2:
[Peer]
PublicKey = ADMIN2_PUBLIC_KEY
AllowedIPs = 10.8.0.3/32Restart:
sudo systemctl restart wg-quick@wg0Ưu điểm:
– Thu hồi 1 người → xóa peer tương ứng. – Audit dễ hơn. – Không phải rotate toàn bộ VPN.
Thu hồi admin:
1. Xóa block [Peer].
2. Restart WireGuard.
3. Xóa SSH public key của admin khỏi ~/.ssh/authorized_keys nếu cần.
Logging và kiểm tra định kỳ
Kiểm tra WireGuard:
sudo wg showXem peer, latest handshake, transfer.
Kiểm tra SSH login:
sudo journalctl -u ssh --since "1 day ago"Kiểm tra auth log:
sudo grep sshd /var/log/auth.logKiểm tra port public từ máy ngoài:
nmap -Pn -p 22,51820 SERVER_PUBLIC_IPKỳ vọng:
– 22/tcp → filtered/closed.
– 51820/udp → open|filtered là bình thường với UDP.
Lỗi thường gặp
Có handshake nhưng không SSH được
Nguyên nhân hay gặp:
– SSH không listen trên 10.8.0.1.
– UFW chặn subnet VPN.
– Client route sai.
– User/key SSH sai.
Debug:
ping 10.8.0.1
nc -vz 10.8.0.1 22
sudo ufw status verbose
ss -tlnp | grep sshKhông có handshake
Kiểm tra:
– Endpoint đúng public IP?
– UDP 51820 mở ở UFW + cloud firewall?
– Server ListenPort đúng?
– Key public/private khớp?
– Client bật tunnel chưa?
Lệnh:
sudo wg
sudo journalctl -u wg-quick@wg0Tự khóa khỏi server
Nếu lỡ chặn SSH public trước khi VPN hoạt động:
– Dùng cloud console/VNC/serial console. – Sửa UFW/sshd_config. – Mở lại SSH tạm:
sudo ufw allow 22/tcp
sudo systemctl restart sshKết luận thực tế
SSH public không còn là mặc định tốt cho server quan trọng. Cấu hình an toàn hơn: WireGuard public, SSH private.
Checklist cuối:
– WireGuard chạy trên wg0.
– Client ping được 10.8.0.1.
– SSH qua 10.8.0.1 OK.
– UFW chỉ allow SSH từ 10.8.0.0/24.
– Public port 22 bị chặn.
– SSH tắt password, tắt root login.
– Mỗi admin có VPN peer riêng.
Mô hình này đơn giản, rẻ, nhanh, hiệu quả. Một port UDP WireGuard thay cho SSH public → bề mặt tấn công giảm mạnh. Với vài dòng config, Ubuntu server kín hơn rất nhiều nhưng vẫn dễ quản trị hằng ngày.
Bình luận (0)
Chưa có bình luận. Hãy là người đầu tiên!