Câu hỏi Làm thế nào để giữ một đường hầm SSH được mở một cách đáng tin cậy?


Tôi sử dụng một đường hầm SSH từ công việc để đi xung quanh tường lửa khác nhau idotic (it's ok với ông chủ của tôi :)). Vấn đề là, sau một thời gian kết nối ssh thường bị treo, và đường hầm bị hỏng.

Nếu tôi ít nhất có thể theo dõi đường hầm tự động, tôi có thể khởi động lại đường hầm khi nó bị treo, nhưng tôi thậm chí còn chưa tìm ra cách để làm điều đó.

Điểm thưởng cho một người có thể cho tôi biết làm thế nào để ngăn chặn kết nối ssh của tôi từ treo, tất nhiên!


200
2017-09-08 13:04


gốc


Đó là đường hầm của bạn chết vì không hoạt động? Tôi đã có vấn đề này khi đường hầm cổng từ điện thoại của tôi vì vậy tôi cuối cùng đã kết thúc sinh sản giả lệnh trên kết nối để làm cho nó "sống" bằng cách sử dụng watch lệnh như: watch -n1 60 echo "wiiiii". Đường hầm sẽ không chết trừ khi mạng bị hỏng hoặc bạn không sử dụng nó. - erm3nda
Liên quan: unix.stackexchange.com/q/200239 - sampablokuper


Các câu trả lời:


Âm thanh như bạn cần autossh. Điều này sẽ theo dõi một đường hầm ssh và khởi động lại nó khi cần thiết. Chúng tôi đã sử dụng nó trong một vài năm và nó có vẻ hoạt động tốt.

autossh -M 20000 -f -N your_public_server -R 1234:localhost:22 -C

Thêm chi tiết về tham số -M đây


239
2017-09-08 13:43



1 cho autossh, nó làm những gì nó nói trên tin. Tôi tin rằng một phần chức năng của nó cũng là gửi các gói theo phong cách lưu động để ngăn chặn bất kỳ loại thời gian chờ nào. - akent
Bạn có thể đặt đường hầm ví dụ bằng cách sử dụng autossh trong câu trả lời? - Ehtesh Choudhury
autossh -f -nNT -i ~/keypair.pem -R 2000:localhost:22 username@myoutsidebox.com   Bạn có thể nhận thấy rằng tôi thiết lập này bằng cách sử dụng -nNT mà không tạo ra một thiết bị đầu cuối từ xa để tôi có thể đặt autossh vào nền, và tùy chọn -i cho SSH để sử dụng một tập tin .pem. Nếu bạn định giữ kết nối luôn luôn, tôi chắc chắn khuyên bạn nên thực hiện cài đặt bổ sung. - juckele
Đối với những gì nó có giá trị, có vẻ như nó thường tốt hơn để bỏ qua -M tham số: bugs.debian.org/cgi-bin/bugreport.cgi?bug=351162 - rinogo
Nếu nó không hoạt động và bạn đang sử dụng các phím, hãy kiểm tra câu trả lời này - serverfault.com/a/545093/288788 - muttonUp


Tất cả tường lửa trạng thái đều quên kết nối sau khi không nhìn thấy gói cho kết nối đó trong một thời gian (để ngăn các bảng trạng thái trở nên đầy các kết nối mà cả hai đầu đều chết mà không đóng kết nối). Hầu hết các triển khai TCP sẽ gửi một gói lưu trữ sau một thời gian dài mà không cần nghe từ phía bên kia (2 giờ là một giá trị chung). Tuy nhiên, nếu có tường lửa stateful mà quên về kết nối trước khi các gói keepalive có thể được gửi đi, một kết nối dài nhưng không hoạt động sẽ chết.

Nếu đúng như vậy, giải pháp là ngăn chặn kết nối không hoạt động. OpenSSH có một tùy chọn gọi là ServerAliveInterval có thể được sử dụng để ngăn không cho kết nối không hoạt động quá lâu (như tiền thưởng, nó sẽ phát hiện khi đồng đội bị chết sớm hơn ngay cả khi kết nối không hoạt động).


34
2017-09-28 13:47



Khoảng thời gian được chỉ định bằng giây, vì vậy bạn có thể cung cấp một số điều chỉnh tinh vi. Nếu tường lửa trạng thái của bạn có thời gian chờ là 5 phút, thì 60 hoặc 120 giây là đủ để giữ kết nối mở. Đó là một trong những cách tôi giữ phiên ssh của tôi thông qua bộ định tuyến của tôi mở. - Darren Hall
Cảm ơn, điều này đã giúp. Nhưng lưu ý (từ một câu trả lời được xếp hạng thấp hơn ở đây, superuser.com/a/146641/115515) nếu bạn chỉ định ServerAliveInterval và không phải là ServerAliveCountMax, bạn có thể tìm thấy ssh cố tình ngắt kết nối sớm hơn bạn muốn. - metamatt
@metamatt, mà xếp hạng thấp hơn câu trả lời bạn tham khảo là thấp hơn xếp hạng vì lý do tốt: IT IS WRONG. - Lambart


Trên máy mac hoặc linux của riêng bạn, cấu hình ssh của bạn giữ cho ssh máy chủ hoạt động cứ 3 phút một lần. Mở một thiết bị đầu cuối và đi của bạn .ssh vô hình của bạn trong nhà của bạn:

cd ~/.ssh/ 

sau đó tạo tệp cấu hình 1 dòng với:

echo "ServerAliveInterval 180" >> config

bạn cũng nên thêm:

ServerAliveCountMax xxxx (high number)

mặc định là 3 vì vậy ServerAliveInterval 180 sẽ ngừng gửi sau 9 phút (3 trong khoảng thời gian 3 phút được chỉ định bởi ServerAliveInterval).


22
2018-05-29 13:45



Lưu ý rằng lệnh của bạn không được khuyến nghị nếu bạn đã có một tập tin cấu hình. Sử dụng >> để chuyển hướng sẽ tốt hơn rất nhiều! - Peltier
tại sao ServerAliveInterval 180 cho chúng tôi 6 phút? trực giác làm cho tôi thử điều này: 180/60 == 3. Vì vậy, không ServerAliveInterval làm việc trong bội số của 30 giây? - nemesisfixx
@mcnemesis: ServerAliveInterval 180 có nghĩa là 3 phút. ServerAliveCountMax mặc định của 3 có nghĩa là 3 trong những khoảng thời gian, vì vậy 9 phút. - metamatt
Tôi đang bỏ phiếu cho câu trả lời này vì cảm ơn vì đã đề cập đến ServerAliveCountMax và điều gì xảy ra nếu bạn chỉ định ServerAliveInterval mà không có ServerAliveCountMax. Nhưng giống như các bình luận trước, tôi nhận thấy tính toán "sẽ ngừng gửi sau" là sai và tôi nghĩ câu trả lời này sẽ tốt hơn nếu nó chỉ cung cấp thông tin về các tùy chọn này, không cho chúng tôi biết cách áp dụng chúng bằng lệnh cd và echo . - metamatt
Downvoting vì nó không có ý nghĩa để thiết lập ServerAliveCountMax thành một "số cao". ServerAliveCountMax chỉ định bao nhiêu lần nó sẽ cố gắng gửi thông điệp "keepalive" trước khi từ bỏ. Mặc định là 3, vì vậy với ServerAliveInterval 180, nó sẽ dừng gửi CHỈ nếu máy chủ KHÔNG ĐƯỢC TRẢ LẠI sau 9 phút, trong trường hợp đó kết nối của bạn có thể là tốt và thực sự chết. - Lambart


Tôi đã sử dụng kịch bản Bash sau đây để tiếp tục sinh ra các đường hầm ssh mới khi đường hầm trước đó chết. Sử dụng một kịch bản có ích khi bạn không muốn hoặc không thể cài đặt các gói bổ sung hoặc sử dụng trình biên dịch.

while true
do
  ssh <ssh_options> [user@]hostname
  sleep 15
done

Lưu ý rằng điều này đòi hỏi một keyfile để thiết lập kết nối tự động nhưng đó là trường hợp với autossh, quá.


20
2017-09-22 14:58



Bạn nên thêm bất kỳ lý do nào mà bạn muốn sử dụng tập lệnh này trên autossh, hoặc là nó chỉ là nó dễ dàng hơn theo cách này? - kyrias
Điều này sẽ không giúp ích nếu ssh tự bị đóng băng, phải không? - nafg
Nó giúp nếu bạn không thể cài đặt mọi thứ trong máy chủ. autossh không được cài đặt sẵn và bureucracy nó đôi khi rất obtuse. - quarkex
Có, thích hợp hơn không phải cài đặt mọi thứ. Tôi đã làm nó theo cách này trong một năm như cách duy nhất của tôi để giữ cho một máy từ xa có thể truy cập (thậm chí thiết lập crontab để chạy nó khi khởi động lại). Nó không bao giờ thất bại, và quan trọng hơn, tôi biết tại sao nó sẽ không bao giờ thất bại. - sudo


Nó chắc chắn trông với tôi rằng bạn đang hiểu sai tất cả ServerAliveCountMax. Theo tôi hiểu các tài liệu, đó là số lượng tin nhắn máy chủ còn sống có thể được trả lời mà không có kết nối bị chấm dứt. Vì vậy, trong những trường hợp như chúng ta đang thảo luận ở đây, việc đặt nó thành một giá trị cao sẽ chỉ đảm bảo rằng kết nối bị treo sẽ không bị phát hiện và chấm dứt!

Đơn giản chỉ cần thiết lập ServerAliveInterval là đủ để giải quyết vấn đề với một tường lửa quên về kết nối, và để lại ServerAliveCountMax thấp sẽ cho phép kết thúc ban đầu để thông báo sự thất bại và chấm dứt nếu kết nối thất bại anyway.

Những gì bạn muốn là, 1) cho kết nối ở trạng thái mở vĩnh viễn trong các trường hợp bình thường, 2) để phát hiện lỗi kết nối và bên khởi tạo để thoát khi không thành công và 3) lệnh ssh được cấp lại mỗi lần các lối ra (cách bạn làm điều đó phụ thuộc rất nhiều vào nền tảng, kịch bản "trong khi đúng" được đề xuất bởi Jawa là một cách, trên OS XI thực sự đã thiết lập một mục launchd).


9
2017-11-28 01:04





Luôn luôn sử dụng ServerAliveInterval Tùy chọn SSH trong trường hợp các vấn đề đường hầm được tạo ra bởi các phiên NAT hết hạn.

Luôn sử dụng phương pháp respawning trong trường hợp kết nối bị hỏng hoàn toàn, bạn có ít nhất ba tùy chọn ở đây:

  • chương trình autossh
  • bash script (while true do ssh ...; sleep 5; done) không xóa lệnh ngủ, ssh có thể thất bại nhanh chóng và bạn sẽ hồi sinh quá nhiều quy trình
  • /etc/inittab, để có quyền truy cập vào một hộp được vận chuyển và cài đặt ở một quốc gia khác, sau NAT, không có cổng chuyển tiếp tới hộp, bạn có thể định cấu hình để tạo đường hầm ssh cho bạn:

    tun1:2345:respawn:/usr/bin/ssh -i /path/to/rsaKey -f -N -o "ServerAliveInterval 180" -R 55002:localhost:22 user@publicip 'sleep 365d'
    
  • kịch bản mới nổi trên Ubuntu, nơi /etc/inittab không có sẵn:

    start on net-device-up IFACE=eth0
    stop on runlevel [01S6]
    respawn
    respawn limit 180 900
    exec ssh -i /path/to/rsaKey -N -o "ServerAliveInterval 180" -R 55002:localhost:22 user@publicip
    post-stop script
        sleep 5
    end script
    

hoặc luôn sử dụng cả hai phương pháp.


9
2018-03-08 21:30



1 cho tùy chọn nội tuyến trong trường hợp bạn không muốn nó cho tất cả các kết nối SSH của bạn - user1146334
Bạn viết "trong trường hợp kết nối đi xuống hoàn toàn". Bây giờ tôi không hiểu, những vấn đề gì autossh sửa chữa chính nó, và những gì nó không? Tôi nghĩ, tất nhiên, nó sẽ chăm sóc của bất kỳ kết nối bị hỏng, như rút cáp trong một vài giờ, nhưng có lẽ không? - Mads Skjern


Systemd là lý tưởng cho việc này.

Tạo một tập tin dịch vụ /etc/systemd/system/sshtunnel.service chứa:

[Unit]
Description=SSH Tunnel
After=network.target

[Service]
Restart=always
RestartSec=20
User=sshtunnel
ExecStart=/bin/ssh -NT -o ServerAliveInterval=60 -L 5900:localhost:5900 user@otherserver

[Install]
WantedBy=multi-user.target

(Sửa đổi lệnh ssh cho phù hợp)

  • điều này sẽ chạy với tư cách người dùng sshtunnel vì vậy hãy đảm bảo rằng người dùng tồn tại trước tiên
  • vấn đề systemctl enable sshtunnel để đặt nó bắt đầu lúc khởi động
  • vấn đề systemctl start sshtunnel để bắt đầu ngay lập tức

Cập nhật tháng 1 năm 2018: một số bản phân phối (ví dụ: Fedora 27) có thể sử dụng chính sách SELinux để ngăn việc sử dụng SSH từ init hệ thống, trong trường hợp đó, chính sách tùy chỉnh sẽ cần phải được tạo để cung cấp miễn trừ cần thiết.


8
2017-07-28 06:10



Điều này trông rất giống với ý chính của tôi: gist.github.com/guettli/… Phản hồi được hoan nghênh! - guettli
Tuyệt vời cho một systemd hệ thống. Nếu một người sử dụng Restart=on-failure sau đó tự sát trình khách SSH sẽ không dẫn đến việc khởi động lại hệ thống bằng SSH với lối thoát thành công. - David Tonhofer
Nếu bạn muốn bắt đầu ssh từ một tập lệnh (bash) được đưa ra làm đối số ExecStart ví dụ để xây dựng ssh danh sách đối số, thực hiện kiểm tra cơ bản, sau đó gọi nó từ tập lệnh như vậy exec /bin/ssh -N .... Đây là lệnh của tôi: exec /bin/ssh -N -oExitOnForwardFailure=Yes -oTCPKeepAlive=no -oServerAliveInterval=5 -oServerAliveCountMax=6 -i "${LOCAL_PRIVATE_KEY}" -L "${TUNNEL_INLET}:${TUNNEL_OUTLET}" "${REMOTE_USER}@${REMOTE_MACHINE}" Ở đâu TUNNEL_INLET="127.0.0.1:3307" và TUNNEL_OUTLET="127.0.0.1:3306" - David Tonhofer


Tôi giải quyết vấn đề này với điều này:

Chỉnh sửa

~/.ssh/config

Và thêm

ServerAliveInterval 15
ServerAliveCountMax 4

Theo trang người đàn ông cho ssh_config:

ServerAliveCountMax
         Sets the number of server alive messages (see below) which may be
         sent without ssh(1) receiving any messages back from the server.
         If this threshold is reached while server alive messages are
         being sent, ssh will disconnect from the server, terminating the
         session.  It is important to note that the use of server alive
         messages is very different from TCPKeepAlive (below).  The server
         alive messages are sent through the encrypted channel and there‐
         fore will not be spoofable.  The TCP keepalive option enabled by
         TCPKeepAlive is spoofable.  The server alive mechanism is valu‐
         able when the client or server depend on knowing when a connec‐
         tion has become inactive.

         The default value is 3.  If, for example, ServerAliveInterval
         (see below) is set to 15 and ServerAliveCountMax is left at the
         default, if the server becomes unresponsive, ssh will disconnect
         after approximately 45 seconds.  This option applies to protocol
         version 2 only.

 ServerAliveInterval
         Sets a timeout interval in seconds after which if no data has
         been received from the server, ssh(1) will send a message through
         the encrypted channel to request a response from the server.  The
         default is 0, indicating that these messages will not be sent to
         the server.  This option applies to protocol version 2 only.

6
2018-05-30 13:32



Mỗi 15 giây có vẻ khá thường xuyên để ping máy chủ. - Lambart
@Lambart nhưng nếu kết nối thực sự là flaky và giảm kết nối thường xuyên, nó ít nhất là phát hiện một kết nối chết và cho cơ hội để thử lại trước đó. - binki


ExitOnForwardFailure yes là một trợ giúp tốt cho các đề xuất khác. Nếu nó kết nối nhưng không thể thiết lập cổng chuyển tiếp thì nó cũng vô dụng đối với bạn như thể nó không kết nối chút nào.


3
2018-06-06 23:41



Đây là một ý tưởng rất tốt. Ngay cả autossh cũng vô ích nếu kết nối trước đó được coi là đã hết thời gian ở phía xa hơn ở máy chủ cục bộ, vì trong trường hợp này máy chủ cục bộ sẽ cố gắng kết nối lại, nhưng không thể thiết lập chuyển tiếp vì cổng vẫn mở. - Raúl Salinas-Monteagudo


Tôi đã có một nhu cầu để duy trì một đường hầm SSH dài hạn. Giải pháp của tôi đã chạy từ một máy chủ Linux, và nó chỉ là một chương trình C nhỏ đáp ứng ssh bằng cách sử dụng xác thực dựa trên khóa.

Tôi không chắc chắn về việc treo, nhưng tôi đã có đường hầm chết do timeouts.

Tôi rất muốn cung cấp mã cho người phản hồi, nhưng tôi dường như không thể tìm thấy nó ngay bây giờ.


1
2017-09-08 13:17





trong khi có những công cụ như autossh giúp khởi động lại phiên ssh ... những gì tôi thấy thực sự hữu ích là chạy lệnh 'screen'. Nó cho phép bạn khôi phục lại các phiên ssh của bạn ngay cả sau khi bạn ngắt kết nối. Đặc biệt hữu ích nếu kết nối của bạn không đáng tin cậy như nó cần.

... đừng quên đánh dấu đây là câu trả lời 'đúng' nếu nó giúp bạn k! ;-)


1
2017-09-08 14:09



... nhưng câu hỏi đặt ra là làm thế nào để giữ cho các đường hầm SSH mở, không chỉ là một phiên đầu cuối. Màn hình IS tuyệt vời mặc dù! - akent
Tôi đã sử dụng màn hình, nhưng nó không giải quyết vấn đề của tôi: - / Cảm ơn câu trả lời của bạn, mặc dù. - Peltier