SSH qua Tor onion service, VPS không mở cổng
Đặt sshd sau Tor onion service để VPS không nhận inbound port nào. Xem setup, client authorization v3 và thứ tự thao tác tránh lockout.
SSH qua Tor onion service thay đổi điều gì
SSH qua Tor onion service cho phép bạn quản trị một VPS không nhận bất kỳ kết nối inbound nào trên bất kỳ cổng nào. Server chủ động kết nối ra mạng Tor và duy trì kết nối đó. Phiên SSH của bạn đi ngược qua kết nối này, nên không có dịch vụ nào phải listen trên địa chỉ IP public.
Tác động lên log xuất hiện ngay lập tức. Một máy có cổng SSH public sẽ nhận hàng nghìn lần thử password thất bại mỗi ngày từ các scanner. Đưa sshd ra sau onion service và chặn traffic inbound trên firewall, khi đó /var/log/auth.log chỉ ghi lại các phiên do bạn khởi tạo.
Đổi lại, tor nằm trên đường đi của mọi phiên quản trị. Đây là một userspace daemon phải khởi động và bootstrap sau mỗi lần reboot trước khi bạn có thể đăng nhập. Hãy tính đến điều này trước khi đóng cổng, vì lỗi ở đây có thể khiến bạn mất quyền truy cập vào một máy mà bạn không thể tiếp cận trực tiếp.
Tạo đường quay lại trước khi thay đổi bất cứ thứ gì
Không bắt đầu cho đến khi bạn có đường khôi phục không sử dụng SSH.
Mở console của nhà cung cấp ngay bây giờ, tức VNC hoặc serial console trong control panel, rồi đăng nhập bằng console đó. Nếu không biết mật khẩu root, đặt lại mật khẩu root từ panel trước và xác nhận mật khẩu hoạt động. Một console bạn chưa từng kiểm tra không phải là đường khôi phục đáng tin cậy.
Thứ tự dưới đây rất quan trọng. Mỗi bước phải được xác nhận trước khi chạy bước tiếp theo, và cổng 22 vẫn mở cho đến khi onion route hoạt động.
- Cài tor và xác nhận tor bootstrap thành công.
- Khai báo onion service và đọc địa chỉ.
- Kết nối qua onion khi cổng 22 vẫn mở.
- Thêm client authorisation, rồi kết nối lại.
- Bind
sshdvào loopback và đóng cổng 22. - Reboot, rồi kết nối lại qua onion.
Giữ phiên SSH hiện tại mở trong suốt quá trình. Một phiên đã thiết lập vẫn tồn tại khi thay đổi firewall chặn các kết nối mới, vì vậy đây là tuyến cứu hộ đầu tiên của bạn.
Cài đặt tor trên server
Ubuntu có tor trong repository riêng, nhưng package ở đó thường cũ hơn. Repository của Tor Project chứa phiên bản được mô tả trong tài liệu của họ. Thêm repository này bằng các lệnh trong hướng dẫn apt repository.
sudo apt update
sudo apt install -y apt-transport-https wget gpg
wget -qO- https://deb.torproject.org/torproject.org/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc | gpg --dearmor | sudo tee /usr/share/keyrings/deb.torproject.org-keyring.gpg >/dev/nullChạy /etc/apt/sources.list.d/tor.sources. Suites lấy codename của bản release, do lsb_release -cs in ra (noble trên Ubuntu 24.04).
Types: deb deb-src
URIs: https://deb.torproject.org/torproject.org/
Suites: noble
Components: main
Signed-By: /usr/share/keyrings/deb.torproject.org-keyring.gpgsudo apt update
sudo apt install -y tor deb.torproject.org-keyring
sudo journalctl -u tor@default -n 20 --no-pagerLog phải kết thúc bằng Bootstrapped 100% (done). Nếu bị kẹt trước dòng đó thì tor không thể kết nối đến network. Nguyên nhân gần như luôn là rule outbound của firewall hoặc clock bị sai nghiêm trọng.
Tên unit dễ gây nhầm. systemctl status tor báo Active: active (exited) ngay cả khi mọi thứ vẫn hoạt động bình thường, vì Debian và Ubuntu đóng gói tor dưới dạng một master unit multi-instance. Unit này chỉ có nhiệm vụ gọi instance thực tế. Daemon chạy dưới tên tor@default.service. Dùng tên đó cho status và journalctl. Các thao tác start, stop và reload với tor vẫn tác động đến instance, nên sudo systemctl reload tor vẫn hoạt động như mong đợi.
Khai báo onion service cho cổng 22
Thêm hai dòng vào /etc/tor/torrc.
HiddenServiceDir /var/lib/tor/ssh/
HiddenServicePort 22 127.0.0.1:22Dòng thứ hai yêu cầu tor nhận cổng ảo 22 trên địa chỉ onion và kết nối đến 127.0.0.1:22 trên máy chủ. Tor truy cập sshd qua loopback. Vì vậy, sau này sshd có thể ngừng lắng nghe trên địa chỉ public.
sudo systemctl reload tor
sudo cat /var/lib/tor/ssh/hostnameLệnh này in ra 56 ký tự base32, theo sau là .onion. Các ký tự đó là public key của service ở dạng mã hóa. Trong cấu hình này không có certificate authority và cũng không cần đăng ký tên ở đâu.
Để tor tự tạo /var/lib/tor/ssh/. Nếu tự tạo thư mục với owner không đúng hoặc mode rộng hơn 0700, tor sẽ từ chối sử dụng và journal sẽ ghi thư mục có quyền quá rộng. Các file bên trong là identity của service: hs_ed25519_secret_key chính là địa chỉ. Hãy backup thư mục đó với mode 600 và lưu bản sao ngoài máy chủ, vì mất thư mục này sẽ làm địa chỉ thay đổi và buộc phải sửa cấu hình trên mọi client.
Kết nối từ workstation của bạn
Workstation cần có tor client và không cần cấu hình gì thêm. Trên Debian hoặc Ubuntu, đó là sudo apt install -y tor netcat-openbsd. Sau đó Tor lắng nghe trên 127.0.0.1:9050 dưới dạng SOCKS5 proxy. SOCKS là một giao thức proxy tổng quát. Phiên bản 5 có thể truyền hostname thay vì địa chỉ IP. Đây là phần quan trọng trong trường hợp này.
OpenSSH không có SOCKS client riêng, nên cần một chương trình hỗ trợ để tạo kết nối. Thêm dòng sau vào ~/.ssh/config.
Host myvps
HostName xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.onion
User admin
ProxyCommand /usr/bin/nc -X 5 -x 127.0.0.1:9050 %h %p
ServerAliveInterval 30-X 5 chọn SOCKS5 và -x 127.0.0.1:9050 trỏ đến tor cục bộ. %h truyền tên onion cho tor dưới dạng hostname, để tor phân giải tên đó bên trong network. Lệnh này phải là OpenBSD netcat. GNU netcat không có tùy chọn -X và sẽ dừng với lỗi nc: invalid option -- 'X'.
ssh myvpsKết nối đầu tiên sẽ chậm vì tor phải xây dựng circuit trước khi thực hiện các bước khác. Chấp nhận fingerprint của host key như khi kết nối ở nơi khác. Từ đây, cách xử lý SSH key thông thường vẫn được áp dụng như cũ. Chỉ có transport thay đổi. Cơ chế xác thực không thay đổi.
Nếu chỉ kết nối một lần, bạn có thể bỏ qua mục cấu hình: torsocks ssh admin@xxxxx.onion thực hiện cùng một việc.
Thêm cơ chế cấp quyền cho client v3
Hiện tại, bất kỳ ai biết địa chỉ đều có thể truy cập banner SSH và bắt đầu thử đoán. Địa chỉ onion không thể được liệt kê từ hệ thống directory, nên địa chỉ này hoạt động như một secret, nhưng vẫn có thể bị lộ theo những cách thông thường: lịch sử shell và các file cấu hình được commit vào git repository. Cơ chế cấp quyền cho client khắc phục lỗ hổng này. Service publish descriptor đã được mã hóa bằng client key, vì vậy người có địa chỉ nhưng không có key thậm chí không thể locate service.
Tạo một cặp key x25519 trên client. Đây là pipeline từ hướng dẫn cấp quyền cho client của Tor Project, với một thay đổi.
openssl genpkey -algorithm x25519 -out /tmp/k1.prv.pem
grep -v " PRIVATE KEY" /tmp/k1.prv.pem | base64 -d | tail --bytes=32 | base32 | sed 's/=//g' > /tmp/k1.prv.key
openssl pkey -in /tmp/k1.prv.pem -pubout | grep -v " PUBLIC KEY" | base64 -d | tail --bytes=32 | base32 | sed 's/=//g' > /tmp/k1.pub.keyPhiên bản được publish của các dòng lệnh đó sử dụng base64pem -d, nhưng Ubuntu cài mặc định không có công cụ này. Khi đó command dừng với base64pem: command not found. GNU base64 -d giải mã cùng phần thân PEM, vì vậy hãy dùng công cụ này thay thế.
Trên server, cài public key.
sudo install -d -m 700 -o debian-tor -g debian-tor /var/lib/tor/ssh/authorized_clients
echo "descriptor:x25519:PASTE_PUBLIC_KEY_HERE" | sudo tee /var/lib/tor/ssh/authorized_clients/laptop.auth >/dev/null
sudo chown debian-tor:debian-tor /var/lib/tor/ssh/authorized_clients/laptop.auth
sudo systemctl reload torChỉ các file kết thúc bằng .auth mới được đọc. Hãy lưu file này thành laptop.auth.txt; nếu không, tor sẽ bỏ qua file mà không in lỗi, và service vẫn âm thầm mở cho bất kỳ ai có địa chỉ.
Trên client, cài private key. Trên Ubuntu, tor daemon chạy dưới user debian-tor và không thể đọc file trong home directory của bạn, vì vậy hãy đặt thư mục ở nơi user đó có thể truy cập.
sudo install -d -m 700 -o debian-tor -g debian-tor /var/lib/tor/onion_auth
echo "ADDRESS_WITHOUT_DOT_ONION:descriptor:x25519:PASTE_PRIVATE_KEY_HERE" | sudo tee /var/lib/tor/onion_auth/myvps.auth_private >/dev/null
sudo chown debian-tor:debian-tor /var/lib/tor/onion_auth/myvps.auth_private
sudo chmod 600 /var/lib/tor/onion_auth/myvps.auth_privateThêm ClientOnionAuthDir /var/lib/tor/onion_auth vào /etc/tor/torrc của client rồi reload tor. Nếu bạn chạy tor bằng user của mình, chẳng hạn bản Homebrew trên macOS, hãy trỏ ClientOnionAuthDir tới ~/.tor/onion_auth với mode 0700.
Địa chỉ trong file đó là 56 ký tự không có hậu tố .onion. Xóa /tmp/k1.prv.pem và /tmp/k1.prv.key khi hoàn tất.
Bây giờ kiểm tra cả hai hướng. ssh myvps vẫn phải kết nối được. Từ một máy không có key, cùng địa chỉ đó phải kết nối thất bại. Lỗi kết nối này xác nhận cơ chế cấp quyền đã hoạt động.
Đóng cổng 22 theo thứ tự này
Trước tiên hãy đặt cơ chế an toàn. Lệnh này sẽ hoàn tác cả hai thay đổi bên dưới sau 15 phút nếu bạn tự khóa mình khỏi máy chủ.
sudo systemd-run --on-active=15m --unit=ssh-rescue \
/bin/sh -c 'ufw allow 22/tcp; rm -f /etc/systemd/system/ssh.socket.d/override.conf; systemctl daemon-reload; systemctl restart ssh.socket'Hủy lệnh bằng sudo systemctl stop ssh-rescue.timer sau khi xác nhận route onion vẫn hoạt động.
Tiếp theo, dừng sshd lắng nghe trên địa chỉ public. Ubuntu 24.04 kích hoạt SSH thông qua socket unit, vì vậy ListenAddress trong sshd_config bị bỏ qua: ssh.socket sở hữu listening socket, không phải sshd. Hãy kiểm tra máy chủ của bạn thuộc trường hợp nào.
systemctl is-enabled ssh.socketNếu lệnh in ra enabled, hãy chạy sudo systemctl edit ssh.socket và thêm dòng này.
[Socket]
ListenStream=
ListenStream=127.0.0.1:22ListenStream= rỗng sẽ xóa giá trị kế thừa từ unit do package cung cấp. Nếu bỏ dòng này, bạn sẽ thêm một listener thứ hai nhưng vẫn giữ listener public. Đây là nguyên nhân phổ biến nhất khiến bước này thất bại mà không báo lỗi rõ ràng.
sudo systemctl daemon-reload
sudo systemctl restart ssh.socket
ss -tlnp | grep ':22'ss phải hiển thị 127.0.0.1:22 và không có gì trên 0.0.0.0:22. Nếu ssh.socket đã bị disable, hãy đặt ListenAddress 127.0.0.1 vào /etc/ssh/sshd_config.d/10-onion.conf, chạy sudo systemctl restart ssh, rồi kiểm tra bằng cùng dòng ss. Trong cả hai trường hợp, output đó là bằng chứng xác nhận.
Tiếp theo là firewall, cụ thể là quản lý rule ufw trên một VPS. Trước tiên chạy sudo ufw status numbered và xóa rule SSH mà lệnh liệt kê.
sudo ufw status numbered
sudo ufw delete allow OpenSSH
sudo ufw default allow outgoing
sudo ufw default deny incoming
sudo ufw status verboseHãy cho phép traffic outbound. Tor kết nối ra các relay trên những cổng như 443 và 9001, nên chính sách outbound default-deny sẽ ngăn Tor bootstrap và đồng thời loại bỏ cách truy cập còn lại duy nhất của bạn. Hầu hết nhà cung cấp cũng có network firewall riêng trong control panel. Hãy đóng cổng 22 ở đó nữa, nếu không cổng này vẫn có thể truy cập bất kể ufw báo gì.
Nếu Docker chạy trên máy này, hãy kiểm tra các port đã publish trước khi kết thúc. Docker tự ghi rule vào cùng các table và publish port của container đi thẳng qua ufw, nên chính sách deny của ufw chưa phản ánh toàn bộ cấu hình.
Khởi động lại trước khi tin cậy
systemctl is-enabled tor@default
sudo rebootNếu lệnh đầu tiên không báo service đã được enable, hãy chạy sudo systemctl enable tor@default trước khi khởi động lại. Chờ 2 phút, rồi chạy ssh myvps. Tor phải bootstrap sau khi boot, nên onion address chỉ bắt đầu phản hồi một thời gian sau khi máy đã khởi động.
Nếu service không khởi động lại, hãy mở console và đọc sudo journalctl -u tor@default -b. Lỗi cú pháp torrc hoặc vấn đề quyền truy cập thư mục sẽ được ghi ở đó. Bạn cũng có thể kiểm tra thay đổi trong torrc trước khi áp dụng.
sudo -u debian-tor tor --verify-configChi phí của cách này so với tunnel WireGuard
So với VPN WireGuard trên VPS của bạn, onion service chậm hơn và khó dự đoán hơn. Hãy đánh giá trung thực sự đánh đổi này trước khi triển khai.
Độ trễ. Circuit của client đi qua ba relay, còn phía service thêm ba relay nữa. Vì vậy, thao tác gõ phím của bạn đi qua khoảng sáu máy được chọn ngẫu nhiên trên toàn thế giới. Gõ tương tác sẽ có độ trễ rõ rệt, còn sao chép file thì chậm. WireGuard chỉ thêm một hop. Hãy đo trường hợp của bạn bằng time ssh myvps 'echo ok', vì kết quả phụ thuộc vào circuit mà tor vừa tạo và sẽ thay đổi khi tor tạo circuit khác.
Userspace daemon nằm trên đường đi chính. WireGuard chạy trong kernel và khởi động cùng network. Tor là một process phải khởi động, bootstrap và kết nối đến guard relay trước khi mọi thứ hoạt động. Khi nó fail, bạn phải dùng console của nhà cung cấp.
Độ chính xác của clock. Descriptor của onion service được publish theo các khoảng thời gian, nên clock sai nghiêm trọng sẽ làm hỏng việc tra cứu địa chỉ mà không có thông báo rõ ràng ở đâu. timedatectl phải báo cáo System clock synchronized: yes.
Đổi lại, bạn có một endpoint không còn phụ thuộc vào việc firewall rule có chính xác hay không. Không có port để scan và không có banner để lấy, đồng thời bản thân địa chỉ là một public key. Vì vậy, endpoint xác nhận danh tính của nó trước cả khi SSH bắt đầu.
Câu trả lời thực tế thường là dùng cả hai. Dùng WireGuard làm đường truy cập hằng ngày và giữ onion service làm route vẫn hoạt động khi WireGuard config bị sai. Như vậy, bạn chỉ cần mở một UDP port thay vì public SSH port. Không cách nào trong số này thay thế cho việc hardening chính sshd: vẫn cần xác thực chỉ dùng key và đăng nhập bằng tài khoản không phải root, vì onion service chỉ bảo vệ network path chứ không bảo vệ những thứ bên ngoài path đó.
Các tình huống lỗi và thông báo bạn sẽ thấy
Tor không bao giờ vượt qua Bootstrapped 0%. Lưu lượng outbound bị chặn hoặc đồng hồ hệ thống lệch quá nhiều. Kiểm tra policy outbound bằng sudo ufw status verbose, sau đó chạy timedatectl.
systemctl status tor báo active (exited). Đây là hành vi bình thường trên Debian và Ubuntu. Đọc tor@default thay thế.
Không tìm thấy descriptor. Tor trả về lỗi mở rộng SOCKS F0, "Onion Service Descriptor Can Not be Found". Descriptor có thể chưa được publish; việc này cần một khoảng thời gian ngắn sau khi reload. Cũng có thể tor trên server chưa chạy.
F4, "Onion Service Missing Client Authorization". Client không có .auth_private tương ứng để tor sử dụng. Kiểm tra ClientOnionAuthDir có trong torrc, thư mục có mode 0700, tên file có phần mở rộng .auth_private và debian-tor có quyền đọc file đó.
F5, "Onion Service Wrong Client Authorization". Private key không khớp với file .auth trên server. Một = ở cuối hoặc ký tự newline thừa bên trong chuỗi base32 có thể gây lỗi này.
nc: invalid option -- 'X'. GNU netcat đã được cài thay vì bản OpenBSD. Chạy sudo apt install -y netcat-openbsd.
Could not resolve hostname. ssh đã thử DNS thông thường, nhưng DNS không có câu trả lời cho .onion, nên ProxyCommand chưa bao giờ chạy. Pattern Host trong ~/.ssh/config không khớp với tên bạn đã nhập.
Permission denied (publickey). Tunnel đã hoạt động và tor đã hoàn tất. Xử lý lỗi này như lỗi publickey bị từ chối do quyền thông thường và không quy lỗi cho tor.
FAQ
Một onion service có thực sự nghĩa là VPS của tôi không còn cổng mở nào không?
Có, sau khi sshd bind vào 127.0.0.1 và firewall drop traffic vào. Tor tạo kết nối TCP outbound đến một relay, rồi phiên kết nối của bạn đi ngược qua relay đó. Vì vậy, không có tiến trình nào trên máy chấp nhận kết nối tại địa chỉ public. Hãy xác minh bằng ss -tlnp trên server và quét cổng từ một nơi khác. Đừng quên firewall mạng riêng của nhà cung cấp trong control panel. Đây là một lớp kiểm soát riêng với ufw và cũng phải được đóng.
Địa chỉ .onion có đủ an toàn để dùng riêng cho SSH không?
Không. Địa chỉ này dài 56 ký tự và không thể bị đoán hoặc liệt kê từ hệ thống directory, nên có tính chất như một secret. Tuy nhiên, nó vẫn có thể lộ qua shell history và các file cấu hình. Hãy bật client authorisation v3. Khi đó, service descriptor được mã hóa bằng client key của bạn. Người chỉ có địa chỉ sẽ nhận lỗi mở rộng F4 và không bao giờ truy cập được đến sshd.
Điều gì xảy ra nếu tor không khởi động sau khi reboot?
Bạn sẽ mất hoàn toàn quyền truy cập SSH vì lúc đó onion address là cách duy nhất để truy cập vào máy. Vì vậy, phải kiểm tra provider console trước khi đóng port 22. Tor cũng cần thời gian bootstrap sau khi boot, nên địa chỉ sẽ phản hồi muộn hơn thời điểm máy bắt đầu trả lời ping. Nếu địa chỉ không bao giờ phản hồi, hãy đăng nhập qua console và đọc sudo journalctl -u tor@default -b. Lỗi cú pháp torrc hoặc lỗi quyền trên /var/lib/tor/ssh sẽ được ghi ở đó.
SSH qua Tor có chậm hơn WireGuard không?
Có, chậm hơn đáng kể. Kết nối đến onion service đi qua khoảng sáu relay được chọn ngẫu nhiên, trong khi WireGuard chỉ đi qua một hop được mã hóa trực tiếp đến server. Thao tác gõ lệnh sẽ có độ trễ và truyền dữ liệu sẽ chậm. Một cấu hình phổ biến là dùng WireGuard cho công việc hằng ngày, còn onion service làm đường truy cập khẩn cấp có thể sử dụng khi cấu hình VPN bị lỗi.