Reading Time: 12 minutes

SSH (viết tắt của Secure Shell) là cách phổ biến nhất để kết nối đến các máy chủ Linux nhằm thực hiện quản trị từ xa. Mặc dù việc kết nối tới một máy chủ duy nhất qua dòng lệnh tương đối đơn giản, có rất nhiều cách để tối ưu hóa quy trình làm việc khi kết nối tới nhiều hệ thống từ xa.

cấu hình SSH Client với OpenSSH

OpenSSH, client SSH dòng lệnh được sử dụng phổ biến nhất trên hầu hết các hệ thống, cho phép bạn cung cấp các tùy chọn kết nối tùy chỉnh. Các tùy chọn này có thể được lưu vào một file cấu hình chứa các tùy chọn khác nhau cho từng máy chủ. Điều này giúp các tùy chọn kết nối bạn sử dụng cho mỗi host được tách biệt và sắp xếp gọn gàng, đồng thời tránh việc phải cung cấp một loạt các tùy chọn dài trên dòng lệnh mỗi khi bạn cần kết nối.

Trong hướng dẫn này, chúng ta sẽ tìm hiểu về cấu trúc của file cấu hình SSH client và cách cấu hình SSH Client với OpenSSH trên Linux

Điều kiện tiên quyết

Để hoàn thành hướng dẫn này, bạn cần có kiến thức cơ bản về SSH và một số tùy chọn mà bạn có thể cung cấp khi kết nối. Bạn cũng nên cấu hình xác thực bằng SSH key cho một số người dùng hoặc máy chủ của mình, ít nhất là cho mục đích thử nghiệm.

Cấu trúc File cấu hình SSH và thuật toán diễn giải

Mỗi người dùng trên hệ thống của bạn có thể duy trì file cấu hình SSH riêng trong thư mục home của họ. Các file này có thể chứa bất kỳ tùy chọn nào mà bạn thường dùng trên dòng lệnh để chỉ định các tham số kết nối. Bạn luôn có thể ghi đè các giá trị đã định nghĩa trong file cấu hình tại thời điểm kết nối bằng cách thêm các flag bổ sung vào lệnh ssh.

Vị trí của File cấu hình SSH Client

File cấu hình phía client nằm tại ~/.ssh/config. Dấu ~ là một lối tắt phổ quát để chỉ thư mục home của bạn. Thông thường, file này không được tạo mặc định, vì vậy bạn có thể cần phải tự tạo nó. Lệnh touch sẽ tạo file nếu nó chưa tồn tại (và cập nhật thời gian sửa đổi lần cuối nếu nó đã có).

touch ~/.ssh/config

Cấu trúc File cấu hình

File config được tổ chức theo các host, tức là theo các máy chủ từ xa. Mỗi định nghĩa host có thể xác định các tùy chọn kết nối cho host cụ thể đó. Wildcard (ký tự đại diện) cũng được hỗ trợ cho các tùy chọn có phạm vi rộng hơn.

Mỗi phần bắt đầu bằng một tiêu đề định nghĩa các host phải khớp với các tùy chọn cấu hình sau đó. Các mục cấu hình cụ thể cho host đó sau đó được định nghĩa bên dưới. Chỉ những mục khác với giá trị mặc định mới cần được chỉ định, vì mỗi mục nhập sẽ thừa hưởng các giá trị mặc định cho bất kỳ mục nào không được định nghĩa. Mỗi phần kéo dài từ một tiêu đề Host đến tiêu đề Host tiếp theo.

Thông thường, vì mục đích sắp xếp và dễ đọc, các tùy chọn được thiết lập cho mỗi host sẽ được thụt lề. Đây không phải là một yêu cầu bắt buộc, nhưng là một quy ước hữu ích giúp dễ dàng diễn giải nhanh chóng.

Định dạng chung sẽ trông giống như thế này:

~/.ssh/config
Host firsthost
    Hostname your-server.com
    User username-to-connect-as
    IdentityFile /path/to/non/default/keys.pem

Host secondhost
    ANOTHER_OPTION custom_value

Host *host
    ANOTHER_OPTION custom_value

Host *
    CHANGE_DEFAULT custom_value

Ở đây, chúng ta có bốn phần sẽ được áp dụng cho mỗi lần cố gắng kết nối, tùy thuộc vào việc host đó có khớp hay không.

Thuật toán diễn giải

Điều quan trọng là phải hiểu cách SSH sẽ diễn giải file để áp dụng các giá trị cấu hình. Điều này có ý nghĩa quan trọng khi sử dụng wildcard và định nghĩa host chung chung Host *.

SSH sẽ so khớp tên host được cung cấp trên dòng lệnh với mỗi tiêu đề Host định nghĩa các phần cấu hình.

Ví dụ, hãy xem xét định nghĩa này:

~/.ssh/config
Host devel
    HostName devel.example.com
    User tom

Host này cho phép chúng ta kết nối với tom@devel.example.com bằng cách gõ lệnh này trên dòng lệnh:

ssh devel

SSH bắt đầu từ đầu file config và kiểm tra từng định nghĩa Host để xem nó có khớp với giá trị được cung cấp trên dòng lệnh hay không. Khi định nghĩa Host khớp đầu tiên được tìm thấy, mỗi tùy chọn SSH liên quan sẽ được áp dụng cho kết nối sắp tới.

SSH sau đó di chuyển xuống file, kiểm tra xem các định nghĩa Host khác có khớp hay không. Nếu một định nghĩa khác được tìm thấy khớp với tên host hiện tại được cung cấp trên dòng lệnh, nó sẽ xem xét các tùy chọn SSH liên quan đến phần mới. Sau đó, nó sẽ áp dụng bất kỳ tùy chọn SSH nào được định nghĩa cho phần mới mà chưa được định nghĩa bởi các phần trước đó.

Đây là một điểm quan trọng. SSH sẽ diễn giải từng phần Host khớp với tên host được cung cấp trên dòng lệnh, theo thứ tự. Trong quá trình này, nó sẽ luôn sử dụng giá trị đầu tiên được cung cấp cho mỗi tùy chọn. Không có cách nào để ghi đè một giá trị đã được cung cấp bởi một phần đã khớp trước đó.

Điều này có nghĩa là file config của bạn nên tuân theo quy tắc: các cấu hình cụ thể nhất nên ở trên cùng. Các định nghĩa chung hơn nên đến sau để áp dụng các tùy chọn chưa được định nghĩa bởi các phần khớp trước đó.

Hãy xem lại ví dụ từ phần trước:

~/.ssh/config
Host firsthost
    Hostname your-server.com
    User username-to-connect-as
    IdentityFile /path/to/non/default/keys.pem

Host secondhost
    ANOTHER_OPTION custom_value

Host *host
    ANOTHER_OPTION custom_value

Host *
    CHANGE_DEFAULT custom_value

Ở đây, chúng ta có thể thấy rằng hai phần đầu tiên được định nghĩa bằng tên host (hoặc biệt danh) theo nghĩa đen, có nghĩa là chúng không sử dụng bất kỳ wildcard nào. Nếu chúng ta kết nối bằng ssh firsthost, phần đầu tiên sẽ là phần đầu tiên được áp dụng. Điều này sẽ thiết lập Hostname, User, và IdentityFile cho kết nối này.

Nó sẽ kiểm tra phần thứ hai và thấy rằng nó không khớp và di chuyển tiếp. Sau đó, nó sẽ tìm thấy phần thứ ba và thấy rằng nó khớp. Nó sẽ kiểm tra ANOTHER_OPTION để xem nó đã có một giá trị cho tùy chọn đó từ các phần trước chưa. Thấy rằng nó chưa có, nó sẽ áp dụng giá trị từ phần này. Sau đó, nó sẽ khớp với phần cuối cùng vì định nghĩa Host * khớp với mọi kết nối. Vì nó không có giá trị cho tùy chọn giả định CHANGE_DEFAULT từ các phần khác, nó sẽ lấy giá trị từ phần này. Kết nối sau đó được thực hiện với các tùy chọn đã thu thập từ quá trình này.

Hãy thử lại, giả vờ gọi ssh secondhost từ dòng lệnh.

Một lần nữa, nó sẽ bắt đầu ở phần đầu tiên và kiểm tra xem nó có khớp không. Vì điều này chỉ khớp với kết nối tới firsthost, nó sẽ bỏ qua phần này. Nó sẽ chuyển sang phần thứ hai. Sau khi tìm thấy phần này khớp với yêu cầu, nó sẽ thu thập giá trị của ANOTHER_OPTION cho kết nối này.

SSH sau đó nhìn vào định nghĩa thứ ba và thấy rằng wildcard khớp với kết nối hiện tại. Nó sẽ kiểm tra xem nó đã có một giá trị cho ANOTHER_OPTION chưa. Vì tùy chọn này đã được định nghĩa trong phần thứ hai, đã được khớp, giá trị từ phần thứ ba bị loại bỏ và không có tác dụng.

SSH sau đó kiểm tra phần thứ tư và áp dụng các tùy chọn bên trong chưa được định nghĩa bởi các phần đã khớp trước đó. Sau đó, nó cố gắng kết nối bằng cách sử dụng các giá trị đã thu thập.

Các tùy chọn kết nối

Bây giờ bạn đã có ý tưởng về cách viết file cấu hình của mình, hãy thảo luận về một số tùy chọn phổ biến và định dạng để sử dụng chúng trên dòng lệnh.

Những tùy chọn đầu tiên chúng ta sẽ đề cập là các thiết lập tối thiểu cần thiết để kết nối đến một host từ xa. Cụ thể là hostname, username, và port mà máy chủ SSH đang chạy.

Để kết nối với một người dùng có tên apollo tới một host có tên example.com đang chạy SSH daemon trên port 4567 từ dòng lệnh, bạn có thể chạy ssh như thế này:

ssh -p 4567 apollo@example.com

Tuy nhiên, bạn cũng có thể sử dụng tên tùy chọn đầy đủ với cờ -o, như thế này:

ssh -o "User=apollo" -o "Port=4567" -o "HostName=example.com"

Bạn có thể tìm thấy danh sách đầy đủ các tùy chọn có sẵn trong trang manual của SSH.

Để thiết lập những điều này trong file config của bạn, bạn phải chọn một tên tiêu đề Host, như home:

Host home
    HostName example.com
    User apollo
    Port 4567

Các tùy chọn cấu hình SSH phổ biến

Cho đến nay, chúng ta đã thảo luận về một số tùy chọn cần thiết để thiết lập một kết nối. Chúng ta đã đề cập đến các tùy chọn này:

  • HostName: Tên host thực tế nên được sử dụng để thiết lập kết nối. Điều này thay thế bất kỳ biệt danh nào được định nghĩa trong tiêu đề Host. Tùy chọn này không cần thiết nếu định nghĩa Host chỉ định địa chỉ hợp lệ thực tế để kết nối.
  • User: Tên người dùng sẽ được sử dụng cho kết nối.
  • Port: Cổng mà SSH daemon từ xa đang chạy. Tùy chọn này chỉ cần thiết nếu phiên bản SSH từ xa không chạy trên port 22 mặc định.

Có nhiều tùy chọn hữu ích khác đáng để khám phá. Chúng ta sẽ thảo luận một số tùy chọn phổ biến hơn, được phân loại theo chức năng.

Các chỉnh sửa chung và mục kết nối

  • ServerAliveInterval: Tùy chọn này có thể được cấu hình để cho SSH biết khi nào gửi một gói tin để kiểm tra phản hồi từ máy chủ. Điều này có thể hữu ích nếu kết nối của bạn không ổn định và bạn muốn biết nó còn khả dụng hay không.
  • LogLevel: Tùy chọn này cấu hình mức độ chi tiết mà SSH sẽ ghi log ở phía client. Điều này có thể được sử dụng để tắt ghi log trong một số tình huống nhất định hoặc tăng độ chi tiết khi cố gắng debug (gỡ lỗi). Từ ít chi tiết nhất đến nhiều nhất, các cấp độ là QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG1, DEBUG2, và DEBUG3.
  • StrictHostKeyChecking: Tùy chọn này cấu hình xem ssh có bao giờ tự động thêm host vào file ~/.ssh/known_hosts hay không. Theo mặc định, tùy chọn này sẽ được đặt thành “ask” (hỏi), có nghĩa là nó sẽ cảnh báo bạn nếu Host Key nhận được từ máy chủ từ xa không khớp với key được tìm thấy trong file known_hosts. Nếu bạn liên tục kết nối tới một số lượng lớn các host ephemeral (ví dụ: máy chủ thử nghiệm), bạn có thể muốn đặt nó thành “no”. SSH sau đó sẽ tự động thêm bất kỳ host nào vào file. Điều này có thể có ý nghĩa bảo mật nếu known hosts của bạn thay đổi địa chỉ khi không nên, vì vậy hãy suy nghĩ cẩn thận trước khi bật nó.
  • UserKnownHostsFile: Tùy chọn này chỉ định vị trí nơi SSH sẽ lưu trữ thông tin về các host mà nó đã kết nối. Thông thường, bạn không phải lo lắng về cài đặt này, nhưng bạn có thể muốn đặt nó thành /dev/null để chúng bị loại bỏ nếu bạn đã tắt strict host checking ở trên.
  • VisualHostKey: Tùy chọn này có thể yêu cầu SSH hiển thị một đại diện ASCII của key của host từ xa khi kết nối. Bật tùy chọn này có thể là một cách hữu ích để làm quen với key của host của bạn, cho phép bạn nhận ra nó nếu bạn phải kết nối từ một máy tính khác vào một thời điểm nào đó trong tương lai.
  • Compression: Bật nén có thể hữu ích cho các kết nối rất chậm. Hầu hết người dùng sẽ không cần điều này.

Với các mục cấu hình trên, chúng ta có thể thực hiện một số chỉnh sửa cấu hình hữu ích.

Ví dụ, nếu chúng ta đang tạo và hủy các host rất nhanh chóng tại một nhà cung cấp cloud, một cái gì đó như thế này có thể hữu ích:

Host home
    VisualHostKey yes

Host cloud*
    StrictHostKeyChecking no
    UserKnownHostsFile /dev/null
    LogLevel QUIET

Host *
    StrictHostKeyChecking ask
    UserKnownHostsFile ~/.ssh/known_hosts
    LogLevel INFO
    ServerAliveInterval 120

Điều này sẽ bật visual host key của bạn cho kết nối home, cho phép bạn làm quen với nó để bạn có thể nhận ra nếu nó thay đổi hoặc khi kết nối từ một máy khác. Chúng ta cũng đã thiết lập bất kỳ host nào bắt đầu bằng cloud* để không kiểm tra host và không ghi log các lỗi. Đối với các host khác, chúng ta có các giá trị dự phòng hợp lý.

Connection Forwarding (chuyển tiếp kết nối)

Một cách sử dụng phổ biến của SSH là chuyển tiếp các kết nối, cho phép một kết nối cục bộ đi qua host từ xa, hoặc cho phép máy từ xa truy cập đi qua máy cục bộ. Điều này đôi khi cần thiết khi bạn cần kết nối đến một máy từ xa phía sau firewall thông qua một máy chủ “cổng” (gateway) riêng biệt, được chỉ định. SSH cũng có thể thực hiện chuyển tiếp động bằng cách sử dụng các giao thức như SOCKS5 bao gồm thông tin chuyển tiếp cho host từ xa.

Các tùy chọn kiểm soát hành vi này là:

  • LocalForward: Tùy chọn này được sử dụng để chỉ định một kết nối sẽ chuyển tiếp lưu lượng truy cập của một cổng cục bộ tới máy từ xa, tạo một đường hầm ra mạng từ xa. Đối số đầu tiên phải là cổng cục bộ bạn muốn chuyển lưu lượng truy cập tới và đối số thứ hai phải là địa chỉ và cổng mà bạn muốn chuyển lưu lượng truy cập tới ở phía từ xa.
  • RemoteForward: Tùy chọn này được sử dụng để định nghĩa một cổng từ xa nơi lưu lượng truy cập có thể được chuyển đến để tạo đường hầm ra khỏi máy cục bộ. Đối số đầu tiên phải là cổng từ xa nơi lưu lượng truy cập sẽ được chuyển đến trên hệ thống từ xa. Đối số thứ hai phải là địa chỉ và cổng để trỏ lưu lượng truy cập tới khi nó đến hệ thống cục bộ.
  • DynamicForward: Điều này được sử dụng để cấu hình một cổng cục bộ có thể được sử dụng với một giao thức chuyển tiếp động như SOCKS5. Lưu lượng truy cập sử dụng giao thức chuyển tiếp động sau đó có thể được chuyển đến cổng này trên máy cục bộ và ở phía từ xa, nó sẽ được định tuyến theo các giá trị đi kèm.

Các tùy chọn này có thể được sử dụng để chuyển tiếp các cổng theo cả hai hướng, như bạn có thể thấy ở đây:

# This will allow us to use port 8080 on the local machine
# in order to access example.com at port 80 from the remote machine
Host local_to_remote
    LocalForward 8080 example.com:80

# This will allow us to offer access to internal.com at port 443
# to the remote machine through port 7777 on the other side
Host remote_to_local
    RemoteForward 7777 internal.com:443

Điều này đặc biệt hữu ích khi bạn cần mở một cửa sổ trình duyệt đến một bảng điều khiển riêng tư hoặc một ứng dụng web khác đang chạy trên một máy chủ không thể truy cập trực tiếp ngoài việc qua SSH.

Other Forwarding (chuyển tiếp khác)

Cùng với việc chuyển tiếp kết nối, SSH cũng cho phép các loại chuyển tiếp khác.

Bạn có thể chuyển tiếp bất kỳ SSH key nào được lưu trữ trong một agent trên máy cục bộ của bạn, cho phép chúng ta kết nối từ hệ thống từ xa bằng cách sử dụng thông tin xác thực được lưu trữ trên hệ thống cục bộ của bạn. Bạn cũng có thể khởi động các ứng dụng trên một hệ thống từ xa và chuyển tiếp màn hình hiển thị đồ họa đến hệ thống cục bộ của chúng ta bằng cách sử dụng X11 forwarding. X11 là một display server của Linux và không dễ sử dụng nếu không có hệ thống máy tính để bàn Linux, nhưng có thể rất hữu ích nếu bạn đang sử dụng cả môi trường Linux từ xa và cục bộ.

Đây là các chỉ thị liên quan đến các khả năng này:

  • ForwardAgent: Tùy chọn này cho phép các authentication key được lưu trữ trên máy cục bộ của chúng ta được chuyển tiếp đến hệ thống mà bạn đang kết nối. Điều này có thể cho phép bạn chuyển từ host này sang host khác bằng cách sử dụng các key home của bạn.
  • ForwardX11: Nếu bạn muốn có thể chuyển tiếp màn hình đồ họa của một ứng dụng đang chạy trên hệ thống từ xa, bạn có thể bật tùy chọn này.

Chỉ định Key

Nếu bạn đã cấu hình SSH key cho các host của mình, các tùy chọn này có thể giúp bạn quản lý key nào để sử dụng cho mỗi host.

  • IdentityFile: Tùy chọn này có thể được sử dụng để chỉ định vị trí của key để sử dụng cho mỗi host. SSH sẽ sử dụng các key nằm trong ~/.ssh theo mặc định, nhưng nếu bạn có các key được gán cho từng máy chủ, tùy chọn này có thể được sử dụng để chỉ định đường dẫn chính xác nơi chúng có thể được tìm thấy.
  • IdentitiesOnly: Tùy chọn này có thể được sử dụng để buộc SSH chỉ dựa vào các identity được cung cấp trong file config. Điều này có thể cần thiết nếu một SSH agent có các key thay thế trong bộ nhớ mà không hợp lệ cho host đang được đề cập.

Các tùy chọn này đặc biệt hữu ích nếu bạn phải theo dõi một số lượng lớn các key cho các host khác nhau và sử dụng một hoặc nhiều SSH agent để hỗ trợ.

Kết luận

Miễn là bạn ghi nhớ cách SSH sẽ diễn giải các giá trị, bạn có thể thiết lập các bộ giá trị cụ thể phong phú với các giá trị dự phòng hợp lý.

Nếu bạn phải sử dụng SSH qua một kết nối rất kém hoặc không liên tục như Wi-Fi trên máy bay, bạn cũng có thể thử sử dụng mosh, được thiết kế để làm cho SSH hoạt động trong các tình huống bất lợi.

0 Bình luận

Đăng nhập để thảo luận

Chuyên mục Hướng dẫn

Tổng hợp các bài viết hướng dẫn, nghiên cứu và phân tích chi tiết về kỹ thuật, các xu hướng công nghệ mới nhất dành cho lập trình viên.

Đăng ký nhận bản tin của chúng tôi

Hãy trở thành người nhận được các nội dung hữu ích của CyStack sớm nhất

Xem chính sách của chúng tôi Chính sách bảo mật.

Đăng ký nhận Newsletter

Nhận các nội dung hữu ích mới nhất