Chuyển tiếp cổng từ xa SSH không thành công


26

Theo dõi: Có vẻ như một loạt các ngắt kết nối nhanh chóng trùng hợp với một vài tháng chạy mỗi máy chủ có lẽ là ngẫu nhiên và chỉ phục vụ để tiết lộ vấn đề thực tế. Lý do nó không kết nối lại gần như chắc chắn là do các giá trị AliveInterval (câu trả lời của kasperd). Sử dụng tùy chọn ExitOnForwardFailure sẽ cho phép thời gian chờ xảy ra đúng trước khi kết nối lại, điều này sẽ giải quyết vấn đề trong hầu hết các trường hợp. Đề xuất của MadHatter (kịch bản giết) có lẽ là cách tốt nhất để đảm bảo rằng đường hầm có thể kết nối lại ngay cả khi mọi thứ khác không thành công.

Tôi có một máy chủ (A) phía sau tường lửa khởi tạo một đường hầm ngược trên một số cổng tới một VPS kỹ thuật số nhỏ (B) để tôi có thể kết nối với A qua địa chỉ IP của B. Đường hầm đã hoạt động ổn định trong khoảng 3 tháng, nhưng đột nhiên thất bại bốn lần trong 24 giờ qua. Điều tương tự cũng xảy ra một thời gian trước trên một nhà cung cấp VPS khác - nhiều tháng hoạt động hoàn hảo, sau đó đột nhiên xảy ra nhiều lỗi nhanh chóng.

Tôi có một tập lệnh trên máy A tự động thực hiện lệnh đường hầm ( ssh -R *:X:localhost:X address_of_Bcho mỗi cổng X) nhưng khi nó thực thi, nó nói Warning: remote port forwarding failed for listen port X.

Đi vào sshd /var/log/securetrên máy chủ cho thấy các lỗi sau:

bind: Address already in use
error: bind: Address already in use
error: channel_setup_fwd_listener: cannot listen to port: X

Việc giải quyết yêu cầu khởi động lại VPS. Cho đến lúc đó, tất cả các nỗ lực để kết nối lại đều đưa ra thông báo "chuyển tiếp cổng từ xa không thành công" và sẽ không hoạt động. Bây giờ đến lúc đường hầm chỉ kéo dài khoảng 4 giờ trước khi dừng lại.

Không có gì thay đổi trên VPS và nó là một máy sử dụng một lần, chỉ sử dụng làm điểm cuối đường hầm ngược. Nó đang chạy OpenSSH_5.3p1 trên CentOS 6.5. Có vẻ như sshd không đóng các cổng khi kết nối bị mất. Tôi không thể giải thích được tại sao, hoặc tại sao nó lại đột nhiên xảy ra sau nhiều tháng hoạt động gần như hoàn hảo.

Để làm rõ, trước tiên tôi cần tìm hiểu tại sao sshd từ chối nghe trên các cổng sau khi đường hầm thất bại, điều này dường như là do sshd để các cổng mở và không bao giờ đóng chúng. Đó dường như là vấn đề chính. Tôi chỉ không chắc điều gì sẽ khiến nó hoạt động theo cách này sau nhiều tháng hành xử như tôi mong đợi (tức là đóng các cổng ngay lập tức và cho phép tập lệnh kết nối lại).


Câu hỏi của bạn là gì? Làm thế nào để giải quyết lỗi liên kết cổng, hoặc làm thế nào để tìm hiểu tại sao ssh lại chết, hoặc một cái gì đó khác?
MadHatter hỗ trợ Monica

Tôi cần tìm hiểu tại sao sshd từ chối mở các cổng trên VPS (lỗi liên kết). Lỗi liên kết cổng dường như là gốc rễ của vấn đề và mọi thứ sẽ hoạt động nếu tôi có thể giải quyết vấn đề đó.
Justin Mrkva

2
Đối với bất kỳ người ẩn nào, thay vì tự tạo một tập lệnh để giữ kết nối mở, chỉ cần sử dụng tự động thay thế, điều này thực hiện cho bạn. serverfault.com/questions/598210/
trộm

Câu trả lời:


27

Tôi đồng ý với MadHatter, có khả năng đó là chuyển tiếp cổng từ các kết nối ssh không còn tồn tại. Ngay cả khi vấn đề hiện tại của bạn hóa ra là một vấn đề khác, bạn có thể mong đợi chạy vào các kết nối ssh không còn tồn tại sớm hay muộn.

Có ba cách kết nối không còn tồn tại như vậy có thể xảy ra:

  • Một trong hai điểm cuối đã được khởi động lại trong khi đầu kia của kết nối hoàn toàn không hoạt động.
  • Một trong hai điểm cuối đã đóng kết nối, nhưng tại thời điểm kết nối bị đóng, đã có sự cố tạm thời về kết nối. Sự cố ngừng hoạt động trong vài phút sau khi kết nối được đóng lại, và do đó đầu kia không bao giờ biết về kết nối đóng.
  • Kết nối vẫn hoàn toàn hoạt động ở cả hai điểm cuối của kết nối ssh, nhưng ai đó đã đặt một thiết bị trạng thái ở đâu đó giữa chúng, đã hết thời gian kết nối do không hoạt động. Thiết bị có trạng thái này sẽ là NAT hoặc tường lửa, tường lửa bạn đã đề cập là một nghi phạm chính.

Chỉ ra điều nào trong ba điều trên đang xảy ra không quan trọng lắm, bởi vì có một phương pháp, sẽ giải quyết cả ba. Đó là việc sử dụng các thông điệp cố định.

Bạn nên xem xét ClientAliveIntervaltừ khóa cho sshd_configServerAliveIntervalkhoảng cho ssh_confighoặc ~/.ssh/config.

Chạy sshlệnh trong một vòng lặp có thể hoạt động tốt. Đó là một ý tưởng tốt để chèn một giấc ngủ trong vòng lặp để bạn không bị ngập máy chủ khi kết nối vì một số lý do không thành công.

Nếu máy khách kết nối lại trước khi kết nối kết thúc trên máy chủ, bạn có thể gặp phải tình huống kết nối ssh mới hoạt động, nhưng không có chuyển tiếp cổng. Để tránh điều đó, bạn cần sử dụng ExitOnForwardFailuretừ khóa ở phía máy khách.


Tôi nghĩ rằng đây có thể là vấn đề. Cụ thể, tập lệnh của tôi trên A sẽ cố gắng kết nối lại với B nếu quá trình ssh chết (tất nhiên vì thông báo cảnh báo không giết quá trình ssh nên nó chỉ bị treo khi điều này xảy ra, nhưng đó là vấn đề cho một ngày khác). Nhưng nếu A cố gắng kết nối lại với B quá nhanh, B có thể đang chờ A kết nối lại. Tôi có lẽ cần đảm bảo B luôn hết thời gian trước khi A kết nối lại. Kết hợp điều đó với đề xuất của MadHatter về việc tiêu diệt các quá trình sshd trước khi kết nối lại có thể sẽ bao gồm 95% các trường hợp có thể xảy ra.
Justin Mrkva

1
Và nói về thông điệp cảnh báo không giết SSH, điều đó khiến tôi suy nghĩ ... và nhìn vào các trang. Hóa ra -o ExitOnForwardFailure yeslà chính xác những gì tôi cần. Vì vậy, đó là một điều ít hơn tôi cần phải tìm ra. Để suy nghĩ, tôi sẽ viết một kịch bản Python để phân tích các thông báo cảnh báo đó. Điều này đơn giản hơn rất nhiều. : D
Justin Mrkva

Xin lỗi vì đã quên ExitOnForwardFailurekhi viết câu trả lời của tôi. Tôi đã thêm nó vào câu trả lời ngay bây giờ.
kasperd

4
Không có vấn đề, và nó đã thực sự -o ExitOnForwardFailure=yes(lưu ý dấu bằng). Vì vậy, nếu bất cứ ai gặp phải điều này, đừng sao chép và dán từ nhận xét trước đó của tôi, nó sẽ không hoạt động. : P
Justin Mrkva

Vì vậy, tôi đã theo dõi máy chủ trong khoảng 10 giờ và có vẻ như nó đang chạy tốt; Tại thời điểm này, tôi cho rằng câu trả lời này là chính xác (tôi chắc chắn khoảng 99% dựa trên những gì tôi đã thấy) và rằng hàng loạt sự ngắt kết nối nhanh chóng là sự trùng hợp liên quan đến các sự cố mạng xảy ra vài tháng sau đó bắt đầu mỗi dịch vụ. Nhờ mọi người giúp đỡ của bạn. ;)
Justin Mrkva

4

Bạn có thể tìm thấy quy trình ràng buộc cổng trên máy chủ đó với

sudo netstat -apn|grep -w X

Có vẻ như rất có thể là một nửa không còn tồn tại sshd, nhưng tại sao lại đưa ra các giả định khi bạn có thể có dữ liệu? Đây cũng là một cách tốt để tập lệnh tìm một PID để gửi tín hiệu 9 đến trước khi cố gắng đưa đường hầm trở lại.


Tôi nhớ đã kiểm tra điều đó trên nhà cung cấp VPS trước đó và tôi đã xác nhận rằng sshd là quá trình lắng nghe các cổng đó. Lần sau nó xảy ra tôi sẽ kiểm tra nó ở đây, nhưng vì hành vi và thiết lập hoàn toàn giống nhau nên tôi không mong đợi nó sẽ khác đi.
Justin Mrkva

Tuyệt vời, vì vậy, kịch bản của bạn sẽ mở lại đường hầm tiêu diệt kẻ bắt cóc cũ trước khi cố gắng làm điều đó.
MadHatter hỗ trợ Monica

Không bao giờ có nhiều hơn một tập lệnh đường hầm (trên A) chạy cùng một lúc, nếu đó là những gì bạn đang nói. Mặt khác, nếu bạn muốn tập lệnh thực hiện từ xa một lệnh trên B để tiêu diệt các quá trình đi lạc ... thì đó thực sự không phải là một ý tưởng tồi. Nhưng một điều đáng lo ngại là liên tục giết chết tất cả các kết nối SSH nếu tôi đang cố gắng gỡ lỗi. Nếu kịch bản trên A luôn giết chết B do trục trặc, thì tôi không thể liên tục bị B đuổi khỏi kịch bản A. : P Tôi sẽ phải kiểm tra để đảm bảo nó không làm điều đó. Nhưng như tôi đã nói, không phải là một ý tưởng tồi. ;)
Justin Mrkva

Tôi đã không nghĩ là có. Bạn nói rằng có một đoạn script chạy trên máy chủ từ xa cố gắng tạo ra một đường hầm và bị lỗi, vì lỗi liên kết và tôi cho rằng nó chỉ chạy khi bạn cần nó (tức là khi đường hầm hiện tại không tốt) bởi vì bạn đã không nói khác. Tất cả những gì tôi đề nghị là nó sẽ giết chết quy trình cụ thể đang giữ cổng mở trước khi nó cố gắng đưa ra đường hầm mới.
MadHatter hỗ trợ Monica

Kịch bản chạy ssh chỉ có trên máy chủ A, máy chủ B là máy chủ vanilla đơn giản không có tập lệnh bổ sung. Những gì tôi có thể làm là viết một tập lệnh kill để đặt trên máy chủ B, sau đó gọi nó từ A nếu không kết nối được một số lần nhất định liên tiếp. Bằng cách đó, nó ít có khả năng can thiệp vào các kết nối SSH khác. Và có lẽ tôi sẽ ghi nhật ký lệnh kill mỗi lần nó chạy và thoát mà không làm gì nếu nó được gọi quá nhiều lần quá nhanh. Cá nhân, có vẻ như giới hạn tỷ lệ bất kỳ kịch bản nào giết chết sshd có lẽ là thận trọng. : P
Justin Mrkva

3

Đối với tôi khi một sshđường hầm bị ngắt kết nối, phải mất một thời gian để kết nối được thiết lập lại để sshquá trình tiếp tục chặn khiến tôi không có đường hầm hoạt động và tôi không biết tại sao. Một giải pháp khắc phục là đưa sshvào nền với -fvà tạo ra các kết nối mới mà không cần chờ kết nối cũ để thiết lập lại. Có -o ExitOnForwardFailure=yesthể được sử dụng để giới hạn số lượng các quy trình mới. Việc -o ServerAliveInterval=60cải thiện độ tin cậy của kết nối hiện tại của bạn.

Bạn có thể lặp lại sshlệnh thường xuyên, giả sử, trong một cronhoặc trong một vòng lặp trong tập lệnh của bạn, ví dụ như sau, chúng tôi sẽ chạy sshlệnh cứ sau 3 phút:

while (1)
do
    ssh -f user@hostname -Rport:host:hostport -N -o ExitOnForwardFailure=yes -o ServerAliveInterval=60
    sleep 180
done

một cách giải pháp mạnh mẽ hơn sẽ là sử dụng autossh
Marco Lavagnino

-o ExitOnForwardFailure=yeslà những gì tôi đang tìm kiếm, cảm ơn rất nhiều!
vadipp

1

Theo kinh nghiệm của tôi, ssh có một thói quen hơi khó chịu là không thoát ra một cách sạch sẽ nếu "cái gì đó" vẫn đang chạy trên hệ thống từ xa. Ví dụ: bắt đầu trong nền. Bạn có thể tái tạo điều này bằng cách:

ssh <server>
while true; do  sleep 60; done&
exit

Ssh của bạn sẽ đăng xuất, nhưng thực tế sẽ không đóng phiên - cho đến khi quá trình từ xa thoát (điều này sẽ không xảy ra, vì đó là vòng lặp 'trong khi đúng'). Nó có thể là một cái gì đó tương tự đang xảy ra - phiên của bạn có một quá trình 'bị mắc kẹt' được sinh ra bởi ssh. Cổng vẫn được sử dụng và do đó nó không thể được sử dụng lại bởi quy trình địa phương của bạn.


Lệnh SSH hoàn chỉnh thực thi trên máy A ssh -o ConnectTimeout=10 -o BatchMode=yes -gnN -R *:X:localhost:X root@$TUNSRV 1>>tunnel.log 2>&1 &vì vậy không có gì được thực thi bởi SSH ngoại trừ chính đường hầm, đặc biệt là do tùy chọn -N. Bất cứ điều gì đang được mở đều được thực hiện trên máy chủ B từ xa bằng cách sử dụng chính sshd.
Justin Mrkva
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.