SSH 원격 포트 전달 실패


26

후속 조치 : 각 서버를 몇 개월 동안 실행 한 것과 같은 일련의 빠른 연결 끊김은 우연의 일치이며 실제 문제를 드러내는 데 도움이됩니다. 다시 연결하지 못한 이유는 AliveInterval 값 (kasperd의 답변) 때문일 것입니다. ExitOnForwardFailure 옵션을 사용하면 다시 연결하기 전에 시간 초과가 올바르게 발생하여 대부분의 경우 문제가 해결됩니다. MadHatter의 제안 (킬 스크립트)은 아마도 모든 것이 실패하더라도 터널을 다시 연결할 수있는 가장 좋은 방법 일 것입니다.

방화벽 뒤에 서버 (A)가 있는데 여러 포트에서 작은 DigitalOcean VPS (B)에 대한 역방향 터널을 시작하여 B의 IP 주소를 통해 A에 연결할 수 있습니다. 터널은 약 3 개월 동안 일관되게 작동했지만 지난 24 시간 동안 갑자기 4 번 실패했습니다. 동일한 작업이 다른 VPS 공급 업체에서 한 달 전에 완벽하게 작동 한 후 갑자기 여러 번의 빠른 오류가 발생했습니다.

머신 A에 자동으로 터널 명령을 실행하는 스크립트가 있습니다 ( ssh -R *:X:localhost:X address_of_B각 포트 X에 대해) Warning: remote port forwarding failed for listen port X. 실행되면이라고 말합니다 .

/var/log/secure서버 에서 sshd로 들어가면 다음 오류가 표시됩니다.

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

해결하려면 VPS를 재부팅해야합니다. 그때까지 모든 재 연결 시도는 "원격 포트 전달 실패"메시지를 표시하며 작동하지 않습니다. 이제 터널이 멈추기 전에 약 4 시간 만 지속되는 지점에 도달했습니다.

VPS에서 변경된 사항은 없으며 리버스 터널 끝점으로 만 사용되는 일회용 단일 사용자 컴퓨터입니다. CentOS 6.5에서 OpenSSH_5.3p1을 실행 중입니다. 연결이 끊어졌을 때 sshd가 끝에서 포트를 닫지 않는 것 같습니다. 몇 달 동안 거의 완벽한 작동 후에 왜 또는 왜 갑자기 발생하는지 설명하지 못했습니다.

명확히하기 위해 먼저 터널이 실패 한 후 sshd가 포트 수신을 거부하는 이유를 알아야합니다 .sshd는 포트를 열어두고 절대 닫지 않기 때문에 발생합니다. 이것이 주요 문제인 것 같습니다. 나는 예상대로 몇 달간 행동 한 후 (예 : 즉시 포트를 닫고 스크립트를 다시 연결할 수 있도록) 어떻게 작동하는지 확실하지 않습니다.


귀하의 질문은 무엇인가? 포트 바인딩 오류를 해결하는 방법 또는 ssh가 왜 죽어 가고 있는지 또는 다른 것을 찾는 방법은 무엇입니까?
MadHatter는 Monica

sshd가 VPS의 포트를 여는 것을 거부하는 이유를 파악해야합니다 (바인드 오류). 포트 바인딩 오류가 문제의 근본으로 보이며 해결할 수 있으면 모든 것이 작동해야합니다.
Justin Mrkva

2
늦은 잠복 자에게는 연결을 유지하기 위해 수동으로 스크립트를 작성하는 대신 autossh를 사용하면됩니다. serverfault.com/questions/598210/…
oligofren

답변:


27

MadHatter에 동의합니다. 이는 ssh 연결이 끊긴 포트 포워딩 일 가능성이 큽니다. 현재 문제가 다른 것으로 밝혀 지더라도 조만간 그러한 ssh 연결이 발생할 수 있습니다.

이러한 기능 불능 연결이 발생할 수있는 세 가지 방법이 있습니다.

  • 연결의 다른 쪽 끝이 완전히 유휴 상태 인 동안 두 끝점 중 하나가 재부팅되었습니다.
  • 두 끝점 중 하나가 연결을 닫았지만 연결이 닫힐 때 연결이 일시적으로 중단되었습니다. 연결이 끊어진 후 몇 분 동안 정전이 지속되었으므로 다른 쪽 끝은 닫힌 연결에 대해 알지 못했습니다.
  • 연결은 여전히 ​​ssh 연결의 두 끝점에서 완전히 작동하지만 누군가가 상태 저장 장치를 그들 사이에 배치하여 유휴로 인해 연결 시간이 초과되었습니다. 이 상태 저장 장치는 NAT 또는 방화벽 일 것입니다. 이미 언급 한 방화벽은 의심스러운 부분입니다.

위 세 가지 중 어떤 것이 일어나고 있는지 파악하는 것은 그리 중요하지 않습니다. 세 가지를 모두 다루는 방법이 있기 때문입니다. 그것은 keepalive 메시지의 사용입니다.

당신은에 보일 것입니다 ClientAliveInterval에 대한 키워드 sshd_configServerAliveInterval대한 간격 ssh_config또는 ~/.ssh/config.

ssh루프 에서 명령을 실행하면 정상적으로 작동 할 수 있습니다. 어떤 이유로 연결이 실패 할 때 서버에 과부하가 발생하지 않도록 루프에 절전 모드를 삽입하는 것이 좋습니다.

서버에서 연결이 종료되기 전에 클라이언트가 다시 연결되면 새 ssh 연결이 작동하지만 포트 전달이없는 상황이 발생할 수 있습니다. 이를 피 ExitOnForwardFailure하려면 클라이언트 측 에서 키워드 를 사용해야합니다 .


이것이 문제가 될 수 있다고 생각합니다. 특히, ssh 프로세스가 종료되면 A의 스크립트가 B에 다시 연결하려고 시도합니다 (물론 경고 메시지가 ssh 프로세스를 종료하지 않기 때문에이 일이 발생하면 중단됩니다.하지만 다른 날 문제입니다). 그러나 A가 B에 너무 빨리 다시 연결하려고하면 B가 A가 다시 연결되기를 기다리는 것일 수 있습니다. A가 다시 연결되기 전에 B가 항상 시간 초과되는지 확인해야합니다. 다시 연결하기 전에 sshd 프로세스를 종료한다는 MadHatter의 제안과 결합하면 가능한 경우의 95 %를 커버 할 것입니다.
저스틴 Mrkva

1
그리고 SSH를 죽이지 않는 경고 메시지에 대해 말하면서, 나는 생각하고 맨 페이지를보고 있습니다. 알고 보니 -o ExitOnForwardFailure yes내가 필요 정확히이다. 그래서 그것은 내가 알아낼 필요가 적은 것입니다. 생각하기 위해 경고 메시지를 구문 분석하기 위해 Python 스크립트를 작성하려고했습니다. 이것은 훨씬 간단합니다. : D
Justin Mrkva

ExitOnForwardFailure답을 쓸 때 잊어 버려서 죄송합니다 . 나는 지금 그것을 대답에 추가했습니다.
kasperd

4
문제가 없었으며 실제로 -o ExitOnForwardFailure=yes(등호를 주목하십시오). 따라서이 문제가 발생하면 이전 의견에서 복사하여 붙여 넣지 마십시오. 작동하지 않습니다. : P
Justin Mrkva

그래서 약 10 시간 동안 서버를 모니터링하고 있으며 제대로 작동하는 것 같습니다. 나는이 시점 에서이 답변이 정확하고 (내가 본 것을 기준으로 약 99 % 확신합니다) 일련의 빠른 연결 끊기가 몇 개월 후에 나타난 네트워크 문제와 우연의 일치라고 가정합니다 각 서비스를 시작합니다. 도와 주셔서 감사합니다. ;)
Justin Mrkva

4

해당 서버의 포트를 바인딩하는 프로세스를 찾을 수 있습니다.

sudo netstat -apn|grep -w X

절반의 손실이 될 것 sshd같지만 왜 데이터를 가질 수 있다고 가정합니까? 또한 스크립트가 터널을 다시 불러 오기 전에 신호 9를 보낼 PID를 찾는 좋은 방법입니다.


이전 VPS 제공 업체에서 확인한 것을 기억하며 sshd가 해당 포트를 수신하는 프로세스임을 확인했습니다. 다음에 이런 일이 생기면 여기에서 확인 하겠지만, 동작과 설정이 완전히 같기 때문에 다른 것으로 기대하지는 않습니다.
Justin Mrkva

터널을 다시 여는 스크립트가 이전 터널 러를 죽이기 전에 죽이십시오.
MadHatter는 Monica

한 번에 하나 이상의 터널 스크립트 (A)가 실행되고있는 것은 아닙니다. 반면에, 스크립트가 원격으로 B에서 명령을 실행하여 스트레이 프로세스를 종료시키려는 경우 실제로 반 나쁜 생각은 아닙니다. 그러나 한 가지 우려는 디버그하려고하면 모든 SSH 연결을 반복적으로 종료하는 것입니다. 결함으로 인해 A의 스크립트가 항상 B를 죽이면, 불량 A 스크립트에 의해 B에서 계속 쫓겨날 수 없습니다. : P 나는 그것을하지 않는지 테스트해야합니다. 그러나 내가 말했듯이, 반 나쁜 생각은 아닙니다. ;)
Justin Mrkva

나는 생각하지 않았다. 원격 서버에서 실행 중이며 바인드 오류로 인해 터널을 불러오고 실패하는 스크립트가 있다고 말하고 필요할 때만 실행한다고 가정합니다 (예 : 기존 터널이 좋지 않은 경우) 다른 말을하지 않았기 때문입니다. 내가 제안하는 것은 새로운 터널을 불러 오기 전에 포트를 열어두고있는 특정 프로세스를 중단한다는 것입니다.
MadHatter는 Monica

ssh를 실행하는 스크립트는 서버 A에만 있고, 서버 B는 추가 스크립트가없는 일반 바닐라 서버입니다. 아마도 내가 할 일은 서버 B에 넣을 킬 스크립트를 작성하고 특정 횟수만큼 연속적으로 연결하지 못하면 A에서 원격으로 호출하는 것입니다. 그렇게하면 다른 SSH 연결을 방해 할 가능성이 줄어 듭니다. 그리고 너무 빨리 호출되면 호출 스크립트 로그가 실행될 때마다 아무것도하지 않고 종료 될 때마다 킬 스크립트 로그가 생길 것입니다. 개인적으로, sshd를 죽이는 스크립트는 속도를 제한하는 것처럼 보입니다. : P
Justin Mrkva

3

나를 위해 때 ssh소위는 연결을 위해 잠시 걸리는 터널의 연결이 끊어 재설정 ssh과정이 더 활성화 된 터널로 날 떠나 차단하기 위해 계속 나는 이유를 알지 못한다. 해결 방법은 이전 연결이 재설정 될 때까지 기다리지 않고 ssh백그라운드 에 넣고 -f새 연결을 생성하는 것입니다. 은 -o ExitOnForwardFailure=yes새로운 프로세스의 수를 LIMT하는 데 사용할 수 있습니다. 는 -o ServerAliveInterval=60현재 연결의 신뢰성을 향상시킨다.

예를 들어, 다음과 같이 스크립트의 루프 또는 루프에서 ssh명령을 자주 반복 할 수 있습니다 cron. 다음과 같이 ssh3 분마다 명령 을 실행합니다 .

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는 로그 아웃하지만 원격 프로세스가 종료 될 때까지 실제로 세션을 닫지 않습니다 ( 'while true'루프이므로 종료되지 않습니다). 세션이 ssh에 의해 생성되는 '고착 된'프로세스를 가지고 있습니다. 포트는 계속 사용 중이므로 로컬 프로세스에서 재사용 할 수 없습니다.


A 시스템에서 실행되는 완전한 SSH 명령 ssh -o ConnectTimeout=10 -o BatchMode=yes -gnN -R *:X:localhost:X root@$TUNSRV 1>>tunnel.log 2>&1 &은 터널 자체를 제외하고 SSH에 의해 실행되는 것이 없으며, 특히 -N 옵션으로 인해 아무 것도 실행되지 않습니다. 열린 상태로 유지되는 것은 sshd 자체를 사용하여 원격 서버 B에서 수행됩니다.
Justin Mrkva
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.