동적 포트 번호를 사용하여 점프 호스트를 통해 SSH

동적 포트 번호를 사용하여 점프 호스트를 통해 SSH

호스트가 3개 있습니다.

  1. 내 컴퓨터.
  2. 고정 IP를 사용하는 점프 호스트(또는 요새)입니다.
  3. 유동 IP를 사용하는 서버 인바운드 포트가 열려 있지 않은 상태에서 NAT 라우터/방화벽 뒤에 있습니다.

서버는 현재 점프 호스트에 연결하고 를 통해 SSH 터널을 설정하므로 -R "0:localhost:22"포트는 점프 호스트에 의해 동적으로 할당됩니다(지금까지는 매우 안정적이었습니다).

몇몇에게는소켓 매직, 점프 호스트의 파일에 동적으로 할당된 포트 번호가 기록되어 있습니다.

이를 통해 Jump Host에 SSH로 연결하고 실행할 수 있습니다.ssh -p $(cat /path/to/port-file) localhost

하지만 이 추가 단계를 건너뛸 수 있습니까?


inventory.yml이는 포트 번호를 업데이트해야 하는 Ansible에 유용합니다 .

server:
  # /usr/bin/ssh jh cat /path/to/port-file
  ansible_port: "34625"
  ansible_host: "localhost"
  ansible_ssh_common_args: "-o ProxyCommand='ssh -q -W %h:%p jh' -o StrictHostKeyChecking=no"

다음을 사용할 수 있습니다 ProxyCommand.

~/.ssh/config내 컴퓨터 파일 에서 명령 대체를 사용할 수 있습니다 .

Host server
  ProxyCommand ssh -q -W localhost:$(echo "34625") jh

echo -n이는 내 로컬 컴퓨터에서 대체가 발생하는 것처럼 보이는 경우 ( 없이도) 작동합니다 .

SSH를 사용하여 포트 번호를 먼저 얻는 비효율성에도 불구하고 이는 작동하지 않습니다.

Host server
  ProxyCommand ssh -q -W localhost:$(ssh jh cat /path/to/port-file) jh

결과는 다음과 같습니다.

Bad packet length 1349676916.
ssh_dispatch_run_fatal: Connection to UNKNOWN port 65535: message authentication code incorrect

그리고 이상하게도 체인 끝에 있는 서버는 인증 로그에 다음을 기록합니다.

sshd[5558]: Bad protocol version identification '' from ::1 port 36048

이는 포트 번호가 반환되고 있음을 의미합니다. 하지만 이 시점에서 왜 깨지는지 모르겠습니다.

그리고 ssh -vvv~/.ssh/known_hosts.


ssh -F /path/to/ssh_config또한 다음 내용을 사용하여 점프 호스트에 사용자 정의 "ssh_config" 파일을 생성해 보았습니다 .

Host tunnel.server
  HostName localhost
  Port 34625

하지만 이것을 와 함께 사용할 수는 없을 것 같습니다 ProxyCommand.


StrictHostKeyChecking=no또한 포트 번호가 변경되면 어느 시점에 도입해야 할 수도 있다고 생각합니다 .

답변1

@anx에서 영감을 얻은 두 번째 부분 솔루션...

소켓 파일 생성

ssh -R '/path/to/socket-file:localhost:22' tunnel@jh

그런 다음 (점프 호스트에서) 이 소켓을 사용하려면 다음을 사용할 수 있습니다 socat.

ssh -o "ProxyCommand socat - UNIX-CLIENT:/path/to/socket-file" localhost

를 사용하는 것은 socat불필요한 단계처럼 보입니다. 소켓 파일을 직접 사용하는 명령을 얻는 방법이 있을 것이라고 확신 ssh하지만 아직 찾을 수 없습니다.

또한 내 컴퓨터에서 이 소켓 파일을 사용하는 방법을 찾지 못했습니다(ProxyCommand는 JumpHost가 아닌 로컬 호스트에서 실행되기 때문에).

나는 또한 주목해야 한다; (점프 호스트의) 계정 은 매우 제한되어 있으므로(터널 연결을 설정하기 위해서만 존재함) 점프 호스트의 내 계정이 이 소켓 파일을 사용할 수 있도록 tunnel설정해야 합니다 . StreamLocalBindMask=0111마찬가지로, 를 통해 새 연결이 설정되면 이전 소켓 파일을 제거해야 합니다 StreamLocalBindUnlink=yes.

이 두 옵션은 모두 점프 호스트의 "/etc/ssh/sshd_config"에서 설정되어야 합니다.

Match User tunnel
  StreamLocalBindMask 0111
  StreamLocalBindUnlink yes

불행하게도 Match2020년 9월 27일에 출시된 OpenSSH 8.4 이전의 "/etc/ssh/sshd_config.d/tunnel.conf"에서는 규칙이 무시됩니다(버그 보고서), 현재 Ubuntu 20.04.1 LTS에서는 사용할 수 없습니다.

답변2

일시적인 해결책이지 이상적이지는 않습니다...

내 컴퓨터에 시간별 크론 작업을 추가하면 점프 호스트에서 포트 번호를 수집하고 새 ~/.ssh/config_tunnels파일이 생성됩니다.

#!/bin/bash

set -u;

config_path="${HOME}/.ssh/config_tunnels";

port=$(/bin/ssh jh /bin/cat /path/to/port-file 2> /dev/null | /bin/sed 's/[^0-9]//g');
if [[ "${port}" -lt 1024 ]]; then
  exit; # Probably a blank/zero value (e.g. connection issue).
fi
    
{
  echo "";
  echo "Host server";
  echo "  ProxyCommand ssh -q -W localhost:${port} jh";
  echo "";
} > "${config_path}";

chown user:group "${config_path}";
chmod 600 "${config_path}";

그런 다음 기본 ~/.ssh/config파일에서 Include ~/.ssh/config_tunnels.

sed참고로 저는 번호를 다시 받고 있는지 확인하기 위해 사용하고 있습니다 . 내 점프 호스트가 손상될 경우 포트 파일에 추가(악성) SSH 구성이 포함되는 것을 원하지 않습니다.

관련 정보