Giới thiệu SSH Tunnel và một số ứng dụng
x-post from kipalog.com
Liệu đây có phải là động lực để mình viết nhiều hơn không? Hy vọng thế.
SSH, viết tắt của Secure Shell
, là một giao thức mã hoá thường được sử dụng để truy nhập vào các máy chủ từ xa (đặc biệt là các máy chủ Linux). Hầu hết các máy chủ Linux đều được cài đặt mặc định một chương trình SSH Server như OpenSSH
hay Dropbear
, sẵn sàng phục vụ các kết nối tới cổng mặc định 22. Ở phía người dùng, có rất nhiều phần mềm để tạo kết nối tới server như PuTTY
cho Windows và ssh
cho Linux/Mac. 2 phương thức xác thực chủ yếu được sử dụng là mật khẩu và khoá công khai. Sau khi đăng nhập thành công, người sử dụng sẽ có quyền sử dụng shell
mặc định hoặc shell
được gán cho người dùng đó. Toàn bộ trao đổi qua lại giữa người dùng và máy chủ được mã hoá với giao thức được chỉ định khi kết nối.
SSH Tunnel cho phép trao đổi dữ liệu thông qua một kênh mã hoá. SSH Tunnel tuy thiết lập rất đơn giản nhưng lại có rất nhiều ứng dụng. Nếu bạn có quyền truy nhập (không nhất thiết phải là root
) tới một máy chủ Linux thì SSH Tunnel sẽ đem lại những lợi ích rất thiết thực. Nếu không thì bạn có thể tham khảo một số server giá rẻ trên trang này: http://lowendbox.com Tôi cũng đang sử dụng một máy chủ dành riêng cho SSH Tunnel với giá chỉ có $15/năm.
Dưới đây là một số ứng dụng phổ biến. Trong đó A
là máy chủ mà bạn có quyền truy nhập SSH. C
là workstation.port_number
là một cổng bất kỳ chưa được sử dụng bởi các chương trình khác (tôi thường chọn cổng > 10000)
SOCKS5 Proxy
Cú pháp:
[user@C ~]$ ssh user@A -D port_number
Câu lệnh trên sẽ khởi tạo một kết nối đến server A
với tên đăng nhập user
, đồng thời thiết lập một SOCKS5 proxy trên máy người dùng ở cổng port_number
. Thay đổi thiết lập socks proxy trên trình duyệt về localhost:port_number
là tất cả các kết nối web từ trình duyệt sẽ được chuyển hướng đến A
và A
sẽ thực hiện các request đến server thực sự và trả về kết quả cho trình duyệt.
Kết nối đến các máy chủ bị giới hạn bởi tường lửa (tạm gọi B
)
Cách này có thể áp dụng trong cả 2 trường hợp: A
có thể kết nối đến B
mà không bị giới hạn bởi tường lửa và A
không thể kết nối đến B
(tất nhiên là B
vẫn có thể kết nối đến A
)
A
có thể kết nối đến B
Đây là trường hợp rất phổ biến ở các công ty hoặc viện nghiên cứu, khi máy chủ A
(thường được gọi là Shell Gateway
) mở cổng 22
. Người dùng tạo kết nối đến A
trước, rồi từ A
kết nối đến các máy khác phía trong tường lửa (ví dụ B
).
Cú pháp (2 câu lệnh dưới đây được thực hiện ở 2 sessions khác nhau:
[user@C ~]$ ssh user@A -D port_number<br /> [user@C ~]$ ssh -o ProxyCommand="nc -x localhost:port_number %h %p" user@B
Câu lệnh đầu tiên khởi tạo một SOCKS5 proxy trên máy người dùng ở cổng port_number
. Câu lệnh thứ 2 sử dụng SOCKS5 proxy đó để kết nối đến server B
A
không thể kết nối đến B
Trong trường hợp này, B
nằm hoàn toàn trong tường lửa và không có bất kỳ một máy chủ nào khác trong cùng mạng với B
nằm ngoài tường lửa.
Bước 1: Khởi tạo một kết nối ssh từ B
đến A
:
[user@B ~]$ ssh -o ServerAliveInterval=5 user@A -R port_number:localhost:22
Câu lệnh trên sẽ khởi tạo một kết nối SSH từ B
đến A
, đồng thời mở cổng port_number
trên A
, có nhiệm vụ chuyển tiếp tất cả các kết nối đến cổng này đến cổng 22
trên máy B
. -o ServerAliveInterval=5
có tác dụng tự động gửi dữ liệu đến server 5 giây một lần để tránh trường hợp A
tự động ngắt kết nối của B
.
Bước 2: Từ C
, kết nối đến A
trước, sau đó đến B
. Lưu ý 2 câu lệnh dưới đây được thực hiện trong cùng một phiên làm việc. Câu lệnh đầu tiên được thực thi ở máy C
. Câu lệnh thứ 2 được thực thi ở máy A
sau khi kết nối giữa C
và A
hoàn tất.
[user@C ~]$ ssh user@A<br /> [user@A ~]$ ssh localhost -p port_number
Nhược điểm của phương án này là kết nối từ B
đến A
phải được thực hiện trước, và bất cứ khi nào có sự cố về đường truyền, khởi động lại, bạn phải thực hiện lại việc kết nối này, trong khi không phải lúc nào bạn cũng có thể kết nối đến B
. Để khắc phục nhược điểm này, tôi có viết một cronjob, thực thi từng phút trên B
để kiểm tra và khởi tạo kết nối khi cần thiết. Dưới đây là nội dung của file thực thi:
forward.sh
<span class="hljs-shebang">#!/bin/bash
</span>
ARGS=<span class="hljs-string">"ssh -o ServerAliveInterval=5 user@A "</span>
ARGS+=<span class="hljs-string">"-R port_number:127.0.0.1:22 "</span>
<span class="hljs-variable">$ARGS</span>
check_alive.sh
<span class="hljs-shebang">#!/bin/bash</span>
DIR=<span class="hljs-string">"<span class="hljs-variable">$( cd "$( dirname "${BASH_SOURCE[0]}" )</span>"</span> && <span class="hljs-built_in">pwd</span> )<span class="hljs-string">"
ps aux | grep ssh | grep user | grep A &> /dev/null
if [ $? -ne 0 ]; then
echo "</span>No SSH tunnel is running!<span class="hljs-string">"
pushd <span class="hljs-variable">$DIR</span> &> /dev/null
./forward.sh &
fi
</span>
cronjob
<span class="hljs-bullet">* </span><span class="hljs-bullet">* *</span> <span class="hljs-bullet">* *</span> /home/user/check_alive.sh
Trên đây là 2 ứng dụng phổ biến của SSH Tunnel. Còn rất nhiều ứng dụng khác nữa tôi sẽ giới thiệu trong các bài viết tiếp theo.