SSH ProxyCommand에 관한 모든 것

SSH ProxyCommand에 관한 모든 것

다음 ProxyCommand에 대한 자세한 설명과 해당 작업의 구체적인 세부 사항을 찾고 있습니다. 가능하다면 철저하게 분석하고 개선할 수 있도록 도와주실 수 있나요? 다른 것이 없다면 가독성을 위해서입니다.

ProxyCommand ssh gatewayserver 'exec 3<>/dev/tcp/targetserver/22; cat <&3 & cat >&3;kill $!'

답변1

/dev/tcp(내 시스템에는 장치가 없지만 다음 섹션에 연결된 TCP 소켓을 bash할당하는 처리 기능이 내장된 것 같습니다 .)/host/port

따라서 ssh 에이전트 명령은 gatewayserver다음을 수행하는 셸을 안전하게 실행합니다.

exec 3<>/dev/tcp/targetserver/22

즉, 파일 설명자 3에 소켓( targetserver/ 에 연결됨)을 연결합니다 port. 그 다음에:

cat <&3 & cat >&3; kill $!

이는 파일 설명자 0(입력) 및 1(출력)과 파일 설명자 (입력 및 출력) 3간의 양방향 리디렉션(두 개의 별도 프로세스 사용) 방법 입니다. 다른 프로세스가 반환된 후 kill $!백그라운드 프로세스를 종료합니다 .cat <&3cat >&3

이들 모두는 좀 더 표준적인 내용에 불과합니다.

ProxyCommand ssh gatewayserver "tcpconnect targetserver port"

명령 대신 /dev/tcp(또는 ) 함수를 사용하세요 .bashtcpconnect


자세한 내용은:

SSH에서 사용하는 프록시 명령은 원격 호스트에 연결하는 방법을 정의하는 데 사용됩니다 targetserver(Ssh 프로토콜이 사용되므로 암호화는 실제로 필요하지 않습니다).초과하다이 채널). 우리의 경우에는 해당 대상 호스트에 대한 연결을 설정하려고 합니다(아마도 방화벽이 직접 gatewayserver연결을 차단하기 때문일 것입니다.targetserver

그래서 프로세스

ssh gatewayserver 'exec 3<>/dev/tcp/targetserver/22; cat <&3 & cat >&3;kill $!'

시작되고:

  • filedescriptor(fd) 1(표준 출력이라고도 함)는 SSH 클라이언트가 대상 호스트에 데이터를 보내는 데 사용됩니다.
  • fd 0(표준 입력이라고도 함)는 SSH 클라이언트가 원격 호스트에서 데이터를 읽는 데 사용됩니다.

ssh gatewayserver첫 번째 홉으로 게이트웨이에 처음 연결하는 데 사용됩니다 . ssh원래 호스트에 있는 프로세스의 fd /fd를 0게이트웨이 호스트에서 실행 중인 셸의 fd /fd로 전달하는 새 셸을 이 호스트에서 시작합니다 . 이 쉘에서 실행되는 명령은 다음과 같습니다.101

exec 3<>/dev/tcp/targetserver/22; cat <&3 & cat >&3;kill $!

명령이 없으면 exec아무 작업도 수행하지 않으며 쉘 자체의 다음 리디렉션만 적용합니다. 일반적인 리디렉션은 다음과 같습니다.

  • n>filefd를 n다음으로 리디렉션합니다(생략된 경우 file쓰기 전용으로 열기 ).n1
  • n<filefd를 n다음으로 리디렉션합니다(생략된 경우 file읽을 수 있도록 엽니다 ).n0
  • n<>filefd를 (읽기 및 쓰기용으로 열림) n로 리디렉션합니다.file
  • n>&m또는 로 지정 n<&m되면 n<>&mfd는 n이전에 fd가 가리킨 파일로 리디렉션됩니다 m.

여기서는 다음이 사용됩니다:

exec 3<>/dev/tcp/targetserver/22

이것은 새로 생성된 fd를 3매우 특별한 파일 /dev/tcp/targetserver/22(실제 파일은 아니지만 bash 자체가 이해하는 파일)로 리디렉션합니다. 여기서 bash는 targetserver포트 22(서버를 찾을 것으로 예상되는 곳 )에서 통신하기 위해 소켓(tcp 프로토콜을 사용하는 특수 파일)을 생성 sshd하고 파일은 fd에서 열립니다(읽기 및 쓰기용) 3.

이제 데이터를 fd 0(클라이언트의 데이터)로 "펌프"하고 이를 fd 3(대상 서버에 대한 연결)로 보내야 합니다. 또한 fd의 데이터를 "펌핑" 3하고 이를 fd 1(클라이언트의 결과)로 다시 보냄으로써 역방향 통신을 보장해야 합니다. 이 두 "펌프"는 cat두 가지 프로세스를 사용하여 설정됩니다.

  • cat <&3( 3 셸의 fd 에서 읽고 씁니다 1.)
  • cat >&3( 0 셸의 fd 에서 읽고 씁니다 3.)

둘 다 cat병렬로 실행되어야 하므로 하나는 백그라운드에서 실행되어야 합니다. 여기서 우리는 fd 0(아마도 tty)에서 읽는 것이 전경에 남아 있기를 원합니다. 이는 다음을 제공합니다:

cat <&3 &  #run in the background
cat >&3; kill $!

kill $!백그라운드 프로세스를 종료하는 데 사용 됩니다 ( $!마지막 백그라운드 프로세스의 pid로 확장됨). 이런 식으로 클라이언트가 중단되면 포그라운드 프로세스가 종료되고 kill이 실행되며 마지막 프로세스도 종료됩니다.

그게 다야! 우리는 다음과 같은 다리를 건설했습니다.

소스 호스트 — (ssh) → 게이트웨이 — (펌프 + 소켓) → 대상 서버(포트 22)

하나 ssh user@targetserver에 대해기원호스트는 다음에 연결할 수 있습니다.표적스승님은 이 다리를 지나가세요!

관련 정보