Làm chủ lệnh socat trên Linux: Chuyển hướng Port, Relay và SSL Tunnel thực chiến

Network tutorial - IT technology blog
Network tutorial - IT technology blog

Khi firewall chặn nhưng công việc vẫn phải chạy

Cách đây hơn 2 năm, mình gặp tình huống khá dở: một server nội bộ trong datacenter chạy dịch vụ trên port 5432 (PostgreSQL), nhưng firewall chỉ cho phép traffic qua port 443. Team developer cần kết nối từ xa mà không muốn đụng vào cấu hình firewall — vì đụng vào là phải mở ticket, chờ duyệt, mất cả ngày.

Giải pháp mình dùng hôm đó là socat. Chạy đúng một lệnh, xong trong 30 giây. Từ đó mình hay dùng tool này mỗi khi cần “nối” hai đầu mạng lại với nhau mà không muốn cấu hình thêm bất cứ thứ gì phức tạp.

socat (viết tắt của SOcket CAT) là công cụ dòng lệnh tạo kết nối hai chiều giữa hai địa chỉ bất kỳ. Hai đầu đó có thể là TCP port, UDP port, Unix socket, file, hay thậm chí stdin/stdout. Nếu netcat là dao bấm bỏ túi thì socat là con dao đa năng có cả tuốc-nơ-vít và mở nắp chai.

socat hoạt động như thế nào?

Chỉ cần nhớ một pattern duy nhất:

socat [options] <address1> <address2>

Khai báo hai “địa chỉ”, socat tự lo phần còn lại — tạo kết nối, chuyển dữ liệu qua lại giữa hai đầu. Địa chỉ hỗ trợ khá nhiều kiểu:

  • TCP:host:port — kết nối TCP tới host:port
  • TCP-LISTEN:port — lắng nghe TCP trên port
  • UDP:host:port / UDP-LISTEN:port — tương tự cho UDP
  • SSL:host:port — kết nối SSL/TLS
  • UNIX-CONNECT:/path/to/socket — Unix domain socket
  • EXEC:/path/to/program — chạy chương trình, pipe stdio
  • STDIN / STDOUT / FILE:/path — file và stdio

Cài đặt nhanh trước khi bắt đầu:

# Debian/Ubuntu
sudo apt install socat

# RHEL/CentOS/Rocky
sudo dnf install socat

Thực hành: Các tình huống hay gặp nhất

1. Chuyển hướng port đơn giản (Port Forwarding)

Đây là use case mình dùng nhiều nhất. Ví dụ: chuyển mọi kết nối đến port 8080 sang port 80 trên cùng máy:

socat TCP-LISTEN:8080,fork TCP:localhost:80

Option fork rất quan trọng — thiếu nó, socat chỉ xử lý đúng một kết nối rồi thoát. Với fork, mỗi kết nối mới được tạo một child process riêng.

Tình huống thực tế hơn: forward port từ máy local lên một server nội bộ không expose ra ngoài:

# Trên jump server (có public IP), forward port 5432 về DB server nội bộ
socat TCP-LISTEN:5432,fork,reuseaddr TCP:192.168.1.50:5432

Option reuseaddr giúp bind lại port ngay sau khi socat restart, không phải ngồi chờ TCP TIME_WAIT timeout (mặc định 60–120 giây).

2. Tạo Relay — chuyển tiếp qua nhiều hop

Mình có office ở Hà Nội và Osaka. Một số dịch vụ nội bộ ở Hà Nội cần được access từ Osaka, nhưng routing trực tiếp bị firewall chặn. Giải pháp là dùng một VPS ở giữa làm relay:

# Trên VPS trung gian (ví dụ Singapore)
# Lắng nghe port 9000, chuyển tiếp sang server Hà Nội port 22
socat TCP-LISTEN:9000,fork,reuseaddr TCP:hanoi-server.internal:22

Từ Osaka, kết nối SSH vào VPS Singapore port 9000 là thực chất đang SSH vào Hà Nội:

ssh -p 9000 [email protected]

Relay kiểu này không mã hóa thêm gì — dữ liệu giữa VPS và server Hà Nội vẫn là plain TCP. Nếu tầng ứng dụng đã mã hóa (SSH, HTTPS) thì không cần lo.

3. UDP Relay — thứ netcat không làm được dễ dàng

UDP relay phức tạp hơn TCP vì không có trạng thái kết nối. socat xử lý ổn với cú pháp riêng:

# Forward UDP port 514 (syslog) sang log server tập trung
socat UDP-RECVFROM:514,fork UDP-SENDTO:logserver.internal:514

Dùng UDP-RECVFROM thay vì UDP-LISTEN để nhiều client có thể gửi đến cùng lúc mà không tranh nhau.

4. SSL Tunnel — ít người biết, hay dùng hơn tưởng

Bạn có dịch vụ plain TCP muốn expose ra ngoài qua kết nối mã hóa, nhưng không muốn dựng nginx hay stunnel? socat làm được, chỉ cần một cert.

Tạo self-signed cert (hoặc dùng cert có sẵn):

openssl req -newkey rsa:2048 -nodes -keyout server.key -x509 -days 365 -out server.crt
cat server.crt server.key > server.pem

Bên server — wrap dịch vụ plain TCP bằng SSL:

# Lắng nghe SSL trên port 8443, forward về plain TCP port 8080 localhost
socat SSL-LISTEN:8443,cert=server.pem,verify=0,fork TCP:localhost:8080

Bên client — kết nối tới SSL endpoint và expose ra local port:

# Kết nối SSL tới server, expose ra local port 8080
socat TCP-LISTEN:8080,fork SSL:yourserver.com:8443,verify=0

Option verify=0 bỏ qua kiểm tra certificate — ổn cho môi trường nội bộ. Production thì dùng cert hợp lệ và bỏ option này đi.

5. Debug nhanh — giả lập server TCP

Khi cần test xem client có kết nối được không, hoặc muốn xem nó gửi gì lên, mình hay dùng:

# Lắng nghe port 8080, in ra terminal những gì client gửi đến
socat -v TCP-LISTEN:8080,fork -

Option -v in cả data lẫn thông tin kết nối theo từng hướng. Tiện hơn Wireshark nhiều khi chỉ cần xem raw request từ một ứng dụng.

Hoặc giả lập server trả về response cố định:

# Mỗi kết nối đến port 9999 sẽ nhận được nội dung file response.txt
socat TCP-LISTEN:9999,fork OPEN:response.txt,rdonly

6. Chạy socat như service với systemd

Trong môi trường office mình quản lý, một số relay cần chạy liên tục. Thay vì để terminal mở, tạo systemd service cho gọn:

# /etc/systemd/system/socat-relay.service
[Unit]
Description=socat port relay 8080 -> internal:80
After=network.target

[Service]
ExecStart=/usr/bin/socat TCP-LISTEN:8080,fork,reuseaddr TCP:192.168.1.10:80
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now socat-relay

Một số lưu ý thực tế

  • Bảo mật: socat không có authentication built-in. Bind ra interface public là bất kỳ ai cũng kết nối được. Kết hợp với ufw/iptables để whitelist IP nguồn.
  • Option bind: Mặc định socat listen trên tất cả interface. Muốn chỉ local thì thêm bind=127.0.0.1: TCP-LISTEN:8080,bind=127.0.0.1,fork
  • IPv6: Dùng TCP6-LISTENTCP6 thay vì TCP nếu cần IPv6.
  • Giới hạn kết nối: Option max-children=10 giới hạn số child process đồng thời — tránh bị flood khi expose ra public.

Khi nào dùng socat, khi nào không?

Mình coi socat là công cụ tình huống — xuất hiện khi cần giải quyết nhanh mà không muốn động vào cấu hình hệ thống. Nó tốt cho:

  • Port forwarding tạm thời (test, debug, sự cố khẩn)
  • Relay đơn giản không cần cấu hình phức tạp
  • Wrap plain TCP thành SSL nhanh
  • Debug giao tiếp network ở tầng thấp

Nhưng đừng dùng socat khi:

  • Cần load balancing hoặc health check → HAProxy/nginx làm tốt hơn nhiều
  • Production reverse proxy cần log, retry, timeout — socat không đủ feature
  • Cần tunnel VPN có mã hóa mạnh → WireGuard/OpenVPN là lựa chọn đúng hơn

30 giây gõ lệnh socat đôi khi hiệu quả hơn 2 tiếng cấu hình thứ khác. Nó không thay thế được HAProxy hay nginx — nhưng cũng không cần thay thế. Mỗi thứ có việc của nó.

Thêm socat vào toolbox ngay nếu chưa có. Không phải lúc nào cũng dùng — nhưng đến khi cần thì không có gì thay thế được.

Share: