다음 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 <&3
cat >&3
이들 모두는 좀 더 표준적인 내용에 불과합니다.
ProxyCommand ssh gatewayserver "tcpconnect targetserver port"
명령 대신 /dev/tcp
(또는 ) 함수를 사용하세요 .bash
tcpconnect
자세한 내용은:
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로 전달하는 새 셸을 이 호스트에서 시작합니다 . 이 쉘에서 실행되는 명령은 다음과 같습니다.1
0
1
exec 3<>/dev/tcp/targetserver/22; cat <&3 & cat >&3;kill $!
명령이 없으면 exec
아무 작업도 수행하지 않으며 쉘 자체의 다음 리디렉션만 적용합니다. 일반적인 리디렉션은 다음과 같습니다.
n>file
fd를n
다음으로 리디렉션합니다(생략된 경우file
쓰기 전용으로 열기 ).n
1
n<file
fd를n
다음으로 리디렉션합니다(생략된 경우file
읽을 수 있도록 엽니다 ).n
0
n<>file
fd를 (읽기 및 쓰기용으로 열림)n
로 리디렉션합니다.file
n>&m
또는 로 지정n<&m
되면n<>&m
fd는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
에 대해기원호스트는 다음에 연결할 수 있습니다.표적스승님은 이 다리를 지나가세요!