- Published on
[MultiTermRunner] SSH Tunneling for Database Access Without VPN
- Authors
- Name
- Đông Trần
- Github
- @dongitran
Cái khó ló giải pháp 👻
Vấn đề gặp phải
Công ty tớ cấp tài khoản VPN trên môi trường dev để có thể truy cập vào các database của công ty, công ty của các bạn có vậy ko ^^
Nhưng không có điều gì để nói đến khi trong đầu mình nảy ra những ý tưởng hay ho, là tạo server nodejs để xây dựng các ứng dụng sáng tạo và hữu ích mà có sử dụng database của công ty để phục vụ công việc 🦠
Một trong những ứng dụng tớ làm là tạo bot Telegram lắng nghe các thay đổi của database mà tớ đã giới thiệu ở bài trước 😄
Vấn đề bây giờ xuất hiện, tớ đã cài VPN trên server ubuntu, công ty chỉ cấp cho một tài khoản VPN thôi, tớ cũng đã thử liên lạc với bạn DevOps của công ty để xin thêm 1 tài khoản VPN nữa nhưng bạn ấy không cho, nên giờ trên máy tính để code không kết nối được database để dev 😭
Nhưng giờ bỏ cuộc sao.... Câu trả lời là không!!!
Giải pháp: SSH Tunneling!
Sau một hồi tìm tòi, mình nhận ra rằng SSH Tunneling chính là giải pháp hoàn hảo. SSH Tunneling cho phép chuyển tiếp các kết nối từ cổng cục bộ trên máy tính của bạn đến máy chủ từ xa thông qua kết nối SSH.
Về cơ bản, mình cần tạo nhiều "đường hầm" SSH từ MacBook đến server Ubuntu (đã có VPN), mỗi đường hầm chuyển tiếp một cổng cục bộ đến một database cụ thể.
Ví dụ cơ bản của một lệnh SSH Tunneling:
ssh -L 3306:mysql-server:3306 username@server
Lệnh này tạo một tunnel từ cổng 3306 trên máy cục bộ đến cổng 3306 trên mysql-server thông qua server trung gian.
Vấn đề mới: Quản lý nhiều tunnel cùng lúc 😫
Công ty tớ có nhiều database ở nhiều port, và có đến tận 9 database khác nhau @@
- 1 MySQL
- 3 PostgreSQL
- 4 MongoDB
- 1 Kafka
Giải pháp đầu tiên của tớ là chạy trên vscode 9 terminal để tạo 9 cái tunnel 😓
Nếu mở 9 terminal và chạy lệnh SSH riêng cho từng cái thì rất mất thời gian và khó quản lý. Sau một hồi tìm kiếm thì tớ tìm thấy extension Terminal Keeper trên VSCode có thể tạo sẵn danh sách terminal(và các lệnh cần terminal đó chạy).
Đến đây thì đã giải quyết được phần nào, nhưng nhược điểm của cái này là mỗi khi VSCode khởi động thì kèm theo phải khởi động 9 terminal này cũng khá nặng. Ngoài ra đôi lúc kết nối ssh có thể tự ngắt kết nối sau khoảng thời gian dài hoặc khi chuyển mạng, mình cần phải reload lại VSCode khá bất tiện
Vì vậy mình vẫn tìm kiếm một giải pháp nào đó để quản lý tự động! Bỗng dưng mình nghĩ ra sao ko dùng 1 server nodejs quản lý các tunnel ssh này? ✨
Giải pháp: MultiTermRunner - Công cụ quản lý SSH Tunneling thông minh 🚀
Từ nhu cầu thực tế, mình đã phát triển một công cụ NodeJS có tên MultiTermRunner để tự động hóa toàn bộ quá trình này.
MultiTermRunner làm gì?
- Mở nhiều terminal SSH cùng lúc
- Tự động chạy các lệnh theo thứ tự đã định
- Tự động phát hiện mất kết nối và kết nối lại
- Tự động giám sát mạng và phục hồi sau khi mạng được khôi phục
Cấu hình của MultiTermRunner
MultiTermRunner sử dụng một cấu hình JSON đơn giản cho các kết nối. Dưới đây là một phần cấu hình tớ đang sử dụng:
[
{
"name": "MySQL",
"commands": [
"pass='my-sudo-password'",
"echo $pass | sudo -S lsof -i :3306 | grep LISTEN | awk '{print $2}' | xargs sudo kill -9",
"ssh -i ~/.ssh/id_rsa -L 3306:mysql-server.example.com:3306 [email protected]"
]
},
{
"name": "PostgreSQL-1",
"commands": [
"pass='my-sudo-password'",
"echo $pass | sudo -S lsof -i :5432 | grep LISTEN | awk '{print $2}' | xargs sudo kill -9",
"ssh -i ~/.ssh/id_rsa -L 5432:postgres-server.example.com:5432 [email protected]"
]
}
]
Mỗi kết nối bao gồm:
- Xác thực sudo để giải phóng cổng nếu đã bị sử dụng
- Tạo SSH tunnel từ cổng cục bộ đến database từ xa
Cách hoạt động
- MultiTermRunner mở một terminal riêng cho mỗi kết nối
- Nó thực hiện các lệnh theo thứ tự đã được định nghĩa
- Liên tục kiểm tra kết nối bằng cách ping hostname
- Tự động tái kết nối nếu phát hiện mất kết nối
- Giám sát mạng và khôi phục tất cả các kết nối sau khi mạng được kết nối lại
Triển khai thực tế
Cài đặt
# Clone repository
git clone https://github.com/dongitran/MultiTermRunner
cd MultiTermRunner
# Cài đặt dependencies
npm install
Cấu hình
- Tạo file
.env
với biếnSESSION_BASE64
chứa cấu hình session đã mã hóa base64 - Thêm biến
EXPECTED_HOSTNAME
để kiểm tra kết nối
Chạy ứng dụng
node index.js
Khi chạy, MultiTermRunner sẽ mở các terminal và thiết lập tất cả các tunnel SSH, giúp bạn kết nối đến tất cả database chỉ bằng một lệnh duy nhất! 🎉
Cấu trúc mã nguồn
Đây là cấu trúc mã nguồn của MultiTermRunner:
src/
├── index.js # Điểm khởi đầu
├── config.js # Cấu hình và hằng số
├── utils/
│ ├── fileUtils.js # Hàm xử lý file
│ └── networkUtils.js # Hàm kiểm tra mạng
├── services/
│ ├── terminalManager.js # Quản lý terminal
│ ├── sessionManager.js # Quản lý session
│ ├── queueManager.js # Quản lý hàng đợi kết nối lại
│ └── networkMonitor.js # Giám sát mạng
└── models/
└── terminal.js # Mô hình terminal
Kết quả đạt được
Sau khi triển khai MultiTermRunner, công việc của mình đã trở nên dễ dàng hơn rất nhiều:
- Không cần lo lắng về mất kết nối - tự động kết nối lại
- Không phải quản lý nhiều terminal SSH riêng biệt
- Tiết kiệm thời gian và tăng hiệu suất làm việc
SSH Tunneling quả thật là một kỹ thuật siêu hay ho để truy cập những tài nguyên từ xa mà không cần VPN, bạn nghĩ sao 🤓
GitHub Repository: MultiTermRunner, các bạn có thể clone về và tùy biến theo ý thích nhé ^^