Помилка віддаленого переадресації порту SSH


26

Продовження: Схоже, швидка серія відключень, що збігається з декількома місяцями роботи кожного сервера, ймовірно, збігається і просто служить для виявлення фактичної проблеми. Причина, через яку не вдалося відновити зв'язок, майже напевно пояснюється значеннями AliveInterval (відповідь Касперда). Використання параметра ExitOnForwardFailure повинно дозволяти належному виникненню тайм-ауту перед повторним підключенням, що повинно вирішити проблему в більшості випадків. Пропозиція MadHatter (сценарій вбивства), мабуть, найкращий спосіб переконатися, що тунель може знову підключитися, навіть якщо все інше вийде з ладу.

У мене є сервер (A) за брандмауером, який ініціює зворотний тунель на декількох портах до невеликого DigitalOcean VPS (B), щоб я міг підключитися до A через IP-адресу Б. Тунель працював послідовно близько 3 місяців, але раптово вийшов з ладу чотири рази за останні 24 години. Те ж саме трапилося ще раз у іншого постачальника VPS - місяці бездоганної роботи, а потім раптом багато швидких збоїв.

У мене є скрипт на машині A, який автоматично виконує тунельну команду ( ssh -R *:X:localhost:X address_of_Bдля кожного порту X), але коли вона виконується, вона каже Warning: remote port forwarding failed for listen port X.

Заходивши в sshd /var/log/secureна сервері, показує ці помилки:

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

Для вирішення потрібен перезавантаження VPS. До цього часу всі спроби відновити з'єднання дають повідомлення про "віддалене переадресація порту не вдалося" і не спрацюють. Зараз до точки, коли тунель триває лише близько 4 годин до зупинки.

У системі VPS нічого не змінилося, і це одноразова користувальницька машина, яка служить лише кінцевою точкою зворотного тунелю. Він працює OpenSSH_5.3p1 на CentOS 6.5. Здається, що sshd не закриває порти на своєму кінці, коли з'єднання втрачено. Мені не вдається пояснити, чому або чому це раптом станеться зараз через місяці майже ідеальної роботи.

Для уточнення спершу мені потрібно з’ясувати, чому sshd відмовляється слухати порти після виходу з ладу тунелю, що, мабуть, викликано тим, що sshd залишає порти відкритими і ніколи їх не закриває. Це, здається, є основною проблемою. Я просто не впевнений, що може змусити його так поводитися через місяці поведінки, як я очікував (тобто закриваю порти відразу і дозволяю сценарію знову підключатися).


Яке Ваше запитання? Як вирішити помилку прив’язки до порту чи як з’ясувати, чому ssh вмирає чи ще щось?
MadHatter підтримує Моніку

Мені потрібно з’ясувати, чому sshd відмовляється відкривати порти на VPS (помилка прив’язки). Помилка прив'язки порту, здається, є коренем проблеми, і все має працювати, якщо я зможу це вирішити.
Джастін Мрква

2
Для будь-яких пізніх ховальників замість того, щоб створити сценарій вручну, щоб створити з'єднання відкритим, просто використовуйте замість автосшів, що робить це для вас. serverfault.com/questions/598210 / ...
oligofren

Відповіді:


27

Я погоджуюсь з MadHatter, що це, ймовірно, переадресація портів із неіснуючих з'єднань ssh Навіть якщо ваша поточна проблема виявиться чимось іншим, ви можете сподіватися рано чи пізно зіткнутися з такими недіючими з'єднаннями ssh.

Існує три способи таких розривів зв'язку:

  • Одну з двох кінцевих точок перезавантажили, а інший кінець з'єднання повністю не працює.
  • Одна з двох кінцевих точок закрила з'єднання, але в той час, коли з'єднання було закрито, на з’єднанні стався тимчасовий відключення. Відключення тривало кілька хвилин після закриття з'єднання, і, таким чином, інший кінець ніколи не дізнався про закрите з'єднання.
  • З'єднання все ще є повністю функціональним в обох кінцевих точках ssh-з'єднання, але хтось поставив десь між ними стан, який призупинив з'єднання через неробство. Цей видатний пристрій буде або NAT, або брандмауером. Брандмауер, про який ви вже згадували, є головним підозрюваним.

З'ясування того, що з вищезгаданих трьох відбувається, не має великого значення, оскільки існує метод, який вирішить усі три. Саме в цьому використовується повідомлення про збереження життя.

Ви повинні вивчити ClientAliveIntervalключове слово для sshd_configта ServerAliveIntervalінтервал для ssh_configабо ~/.ssh/config.

Запуск sshкоманди в циклі може добре працювати. Це добре, щоб вставити сон у циклі також таким чином, що ви не закінчите затоплювати сервер, коли з'єднання з якихось причин виходить з ладу.

Якщо клієнт знову підключиться до того, як з'єднання припиниться на сервері, ви можете опинитися в ситуації, коли новий ssh-з'єднання живе, але не має переадресації порту. Щоб уникнути цього, вам потрібно використовувати ExitOnForwardFailureключове слово на стороні клієнта.


Я думаю, що це може бути проблемою. Зокрема, мій сценарій на A спробує знову підключитися до B, якщо процес ssh загине (звичайно, оскільки повідомлення попередження не вбиває ssh-процес, він просто зависає, коли це станеться, але це проблема для іншого дня). Але якщо A намагається відновити зв'язок із B занадто швидко, B може чекати, коли A відновиться. Напевно, я повинен переконатися, що B завжди вичерпується, перш ніж A підключиться. Поєднавши це, з пропозицією MadHatter вбити процеси sshd перед повторним підключенням, мабуть, буде охоплено 95% можливих випадків.
Джастін Мрква

1
І якщо говорити про попереджувальне повідомлення, що не вбиває SSH, це задумало мене ... і дивлячись на manpages. Виявляється, -o ExitOnForwardFailure yesсаме те, що мені було потрібно. Тож це ще одна менша річ, яку мені потрібно розібратися. Для думки я збирався написати сценарій Python для розбору цих попереджувальних повідомлень. Це набагато простіше. : D
Джастін Мрква

Вибачте, що забули про те, ExitOnForwardFailureколи писали свою відповідь. Я додав це до відповіді зараз.
kasperd

4
Без проблем, і це було насправді -o ExitOnForwardFailure=yes(зверніть увагу на знак рівності). Тож якщо хтось стикається з цим, не копіюйте та не вставляйте з мого попереднього коментаря, це не спрацює. : P
Джастін Мрква

Тому я спостерігаю за сервером близько 10 годин, і, схоже, він працює нормально; На даний момент я припускаю, що ця відповідь є правильною (я приблизно на 99% впевнений, виходячи з побаченого) і що серія швидких відключень була збігом, пов’язаною з мережевими проблемами, які щойно траплялися через кілька місяців після починаючи кожну послугу. Дякую всім за допомогу. ;)
Джастін Мрква

4

Ви можете знайти процес, що зв'язує порт на цьому сервері

sudo netstat -apn|grep -w X

Здається, це дуже ймовірно, що це напівпрогноз sshd, але навіщо робити припущення, коли можна мати дані? Це також хороший спосіб для сценарію знайти PID, щоб відправити сигнал 9 до того, як спробувати знову підняти тунель.


Я пам'ятаю, що перевіряв це на попередньому постачальнику VPS, і я підтвердив, що sshd - це процес прослуховування цих портів. Наступного разу, коли це станеться, я перевірю це тут, але оскільки поведінка та налаштування абсолютно однакові, я не очікую, що це буде інакше.
Джастін Мрква

Чудово, так що ваш сценарій, який повторно відкриває тунель, вбиває старий тунелер, перш ніж намагатися це зробити.
MadHatter підтримує Моніку

Ніколи не працює одразу більше одного сценарію тунелю (на А), якщо це так, що ви говорите. З іншого боку, якщо ви хочете, щоб сценарій віддалено виконував команду на B, щоб вбити бродячі процеси ... це насправді не наполовину погана ідея. Але одне занепокоєння - це неодноразове відключення всіх SSH-з'єднань, якщо я намагаюся налагоджувати. Якщо сценарій на A завжди вбиває B через глюк, я не можу постійно відбивати B від сценарію ізгоя A. : P Мені доведеться перевірити, щоб переконатися, що це не зробить. Але, як я вже сказав, не наполовину погана ідея. ;)
Джастін Мрква

Я не думав, що є. Ви кажете, що на віддаленому сервері працює сценарій, який намагається підняти тунель і виходить з ладу через помилку прив’язки, і я припускаю, що він працює лише тоді, коли вам це потрібно (тобто, коли існуючий тунель не є корисним) тому що ви не сказали іншого. Все, що я припускаю, це те, що він знищує специфічний процес, який тримає порт відкритим, перш ніж він намагається підняти новий тунель.
MadHatter підтримує Моніку

Сценарій, на якому працює ssh, є лише на сервері A, сервер B - звичайний ванільний сервер без зайвих сценаріїв. Я, мабуть, буду писати сценарій вбивства, який потрібно поставити на сервер B, а потім віддалено викликати його з A, якщо він не зможе з'єднати певну кількість разів поспіль. Таким чином, менше шансів заважати іншим з'єднанням SSH. І я, мабуть, матиму журнал сценарію вбивства кожного разу, коли він запускається та виходить, не роблячи нічого, якщо він викликається занадто багато разів занадто швидко. Особисто мені здається, що обмеження швидкості будь-якого сценарію, що вбиває sshd, ймовірно, розсудливий. : P
Джастін Мрква

3

Для мене, коли sshтунель відключається, потрібне деякий час, щоб з'єднання було скинуто, тому sshпроцес продовжує блокувати, залишаючи мене без активних тунелів, і я не знаю, чому. Рішення для вирішення проблеми полягає в тому, щоб вивести sshна задній план -fі нерестовити нові з'єднання, не чекаючи, коли старі з'єднання будуть скинуті. -o ExitOnForwardFailure=yesМоже бути використані для НТА кількості нових процесів. -o ServerAliveInterval=60Підвищує надійність вашого поточного з'єднання.

Ви можете повторювати sshкоманду часто, скажімо, в a cronабо або в циклі у вашому сценарії, наприклад, у наступному, ми виконуємо sshкоманду кожні 3 хвилини:

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

способом більш надійного рішення буде використання autossh
Marco Lavagnino

-o ExitOnForwardFailure=yesбуло те, що я шукав, велике спасибі!
vadipp

1

На мій досвід, ssh має трохи набридливу звичку не виходити чисто, якщо "щось" все ще працює на віддаленій системі. Наприклад, починається на задньому плані. Ви можете відтворити це:

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

Ваш ssh вийде, але фактично не закриє сеанс - до тих пір, поки віддалений процес не завершиться (чого не буде, оскільки це цикл "в той час як справжній"). Можливо, відбувається щось подібне - ваш сеанс має "застряглий" процес, породжений ssh. Порт залишається у використанні, і тому він не може бути використаний локальним процесом.


Повна команда SSH, яка виконується на машині A, означає ssh -o ConnectTimeout=10 -o BatchMode=yes -gnN -R *:X:localhost:X root@$TUNSRV 1>>tunnel.log 2>&1 &, що SSH нічого не виконує, крім самого тунелю, зокрема через опцію -N. Що б не було відкрито, робиться на віддаленому сервері B, використовуючи сам sshd.
Джастін Мрква
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.