Secure Ubuntu bằng WireGuard: Chặn SSH ngoài mạng riêng

P P T P Chung

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ộ:

ssh [email protected]

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ảnh báo: Đừng khóa SSH public trước khi xác nhận WireGuard hoạt động. Luôn giữ 1 session SSH hiện tại mở trong lúc test.

Cài WireGuard trên Ubuntu server

Cập nhật pkg:

sudo apt update
sudo apt install -y wireguard

Tạ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.key

Xem key:

sudo cat /etc/wireguard/server_private.key
sudo cat /etc/wireguard/server_public.key

Tạo config server:

sudo nano /etc/wireguard/wg0.conf

Nộ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.keyCLIENT_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.key

Trê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@wg0

Kiểm tra:

sudo wg
ip addr show wg0

Mở UDP port 51820 trên firewall/cloud firewall.

Nếu dùng UFW:

sudo ufw allow 51820/udp

Nế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.1

Nếu ping OK, thử SSH qua VPN:

ssh [email protected]

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 tcp

Từ chối SSH public:

sudo ufw deny 22/tcp

Bảo đảm WireGuard vẫn mở:

sudo ufw allow 51820/udp

Bật UFW nếu chưa bật:

sudo ufw enable
sudo ufw status verbose

Thứ tự rule UFW có thể ảnh hưởng. Kiểm tra:

sudo ufw status numbered

Bạ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:

ssh [email protected]

Test từ ngoài VPN:

ssh user@SERVER_PUBLIC_IP

Kỳ 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_config

Thêm/sửa:

ListenAddress 10.8.0.1

Kiểm tra config:

sudo sshd -t

Restart SSH:

sudo systemctl restart ssh

Kiểm tra socket:

ss -tlnp | grep ssh

Kỳ vọng:

LISTEN 0 128 10.8.0.1:22 ...

Không nên thấy:

0.0.0.0:22
Lưu ý quan trọng: Nếu SSH khởi động trước WireGuard, IP 10.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_config

Khuyến nghị:

PasswordAuthentication no
PermitRootLogin no
PubkeyAuthentication yes
KbdInteractiveAuthentication no
X11Forwarding no
AllowUsers youruser

Test 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/32

Restart:

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 show

Xem 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.log

Kiểm tra port public từ máy ngoài:

nmap -Pn -p 22,51820 SERVER_PUBLIC_IP

Kỳ 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 ssh

Khô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@wg0

Tự 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 ssh

Kế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.

Tác giả

P T P

Chia sẻ

Bài viết liên quan

Bình luận (0)

Email của bạn sẽ không được hiển thị công khai.

Chưa có bình luận. Hãy là người đầu tiên!