로컬 포트 ​​또는 소켓 파일을 원격 소켓 파일로 전달


24

빠른 질문-두 개의 Linux 상자를 실행합니다. 하나는 내 데스크탑이고 다른 하나는 VPS입니다. VPS 측의 보안상의 이유로 MySQL ( /var/run/mysqld/mysql.sock)에 대한 소켓 연결을 선택했습니다 . : 나는이 같은 터널을 수있어 ssh -L 3307:127.0.0.1:3306 user@site.com내가 어떤 포트에서 수신 대기 할 수있는 원격 SQL 서버를 설정 한 경우,하지만 내가 알고 싶은 것은 내가 같은 것을 할 수 있습니다 : ssh -L /path/to/myremotesqlserver.sock:/var/run/mysqld/mysql.sock두 개의 포트에 반대하여 두 개의 소켓을 터널링을?

완벽하게 수용 가능한 해결책은 로컬 포트를 원격 소켓 파일로 전달하는 것이지만 가능한 경우 원격 상자에서 tcp 서버를 실행하지 않으려 고합니다.

(예, tcp가 더 쉽다는 것을 알고 있습니다).


mySQL 상자에서 TCP를 사용하지 않으려는 이유가 보안 문제 (예 : 원격 공격 등)로 인해 방화벽을 막을 수 있고 방화벽이 충분하지 않으면 mySQL 만 127.0.0.1을 수신하게하십시오. TCP 연결의 경우 SSH를 통해 쉽게 터널링 할 수 있습니다. 그렇지 않은 경우 아래의 socat 솔루션을 지원합니다.
Mattias Ahnberg

lwn.net/Articles/609321 OpenSSH 6.7로 소켓 포워딩
Hubbitus

@Hubbitus는 현재이 기능을 사용할 수 있습니다. 그렇다면 예 답변을 제공 할 수 있습니까?
CMCDragonkai

그 의견은 답변 형식이지만 누군가에 의해 의견으로 변환되었습니다. 그리고 지금 당신은 이미 아래의 대답을 제안합니다.
Hubbitus

답변:


35

요청시 로컬 소켓 전달

  • SSH 공개 키 인증 설정
  • socat양쪽 끝에 설치
  • 다른 사용자가 액세스 할 수없는 소켓 용 로컬 디렉토리를 작성하십시오.
export SOCKET_DIR=~/.remote-sockets
mkdir -p $SOCKET_DIR
socat "UNIX-LISTEN:$SOCKET_DIR/mysqld.sock,reuseaddr,fork" \
EXEC:'ssh user@server socat STDIO UNIX-CONNECT\:/var/run/mysqld/mysqld.sock'

그때

mysql -S $SOCKET_DIR/mysqld.sock -u mysqluser -p

ssh와 socat으로 유닉스 도메인 소켓전달하지 못함


이것은 굉장하며 허용되는 대답이어야합니다.
John Smith 선택 사항

32

질문이 제기되었을 당시에는 실제로 불가능했지만 오늘날 가능합니다.

UNIX => TCP 및 UNIX => UNIX 전달 둘 다 수행 할 수 있습니다.

예를 들면 다음과 같습니다.

ssh \
  -R/var/run/mysql.sock:/var/run/mysql.sock \
  -R127.0.0.1:3306:/var/run/mysql.sock \
  somehost

OpenSSH 6.7부터 가능합니다.


1
위의 방법을 사용하여 로컬 소켓을 원격 서버 소켓에 전달하고 도커 클라이언트를 원격으로 실행했습니다 (ssh로 직접 수행 할 수는 있지만 재미는 어디에 ssh -L /home/user/docker.sock:/var/run/docker.sock dockerhost -N
있습니까?)

11

나는 이것을하지 않았지만 socat으로 시도 할 것 입니다. 아마도 다음과 같은 것 :

ssh xxx@yyy.zzz -L 9999:localhost:9999 "socat TCP-LISTEN:localhost:9999 UNIX-CONNECT:/var/run/mysqld/mysql.sock"
socat UNIX-LISTEN:/path/to/local/socket TCP:localhost:9999

다시 말하지만, 나는 이런 일을 한 적이 없습니다.


나는 그것을 갈 것이고 그것이 어떻게 진행되는지 알려줄 것입니다. tcp 기반 구현을 사용하고 있습니다.

나는 그것이 현재 작동하도록 할 수는 없지만 어쨌든 아이디어에 +1합니다. 문제를 해결하면 알려 드리겠습니다.

+1은 유용한 유틸리티처럼 보입니다.
워너

5

ssh 6.7 이후 더 이상 socat이 필요하지 않습니다. 다음과 같이 유닉스 도메인 소켓을 직접 전달할 수 있습니다.

ssh -nNT -L $(pwd)/docker.sock:/var/run/docker.sock user@someremote

자세한 정보 : https://medium.com/@dperny/forwarding-the-docker-socket-over-ssh-e6567cfab160


또한 다른 사용자로 로컬 소켓에 연결하는 데 유용하다는 것을 알았습니다. 이를 통해 특정 사용자 ID의 연결을 끊는 서버 프로세스에 대해 클라이언트 프로그램을 실행할 수 있습니다 (자체 작업 실행기에서 오는 연결).
Warbo

sshd를 사용하여 액세스를 인증하기 위해 소켓을 동일한 컴퓨터로 전달하지만 다른 사용자가 제어하는 ​​다른 디렉토리를 전달합니까? 사용 사례는 무엇입니까?
CMCDragonkai 1

디렉토리 권한 / 액세스는 문제가되지 않습니다. 오히려 특정 데몬 은 특정 그룹의 사용자가 시도한 연결 시도를 삭제합니다 (아마도 초보자가 혼동되는 것을 방지하기 위해). ssh를 사용하면 해당 사용자가 해당 그룹에없는 사용자처럼 터널링 된 소켓을 통해 연결할 수 있으므로 연결이 끊어지지 않습니다.
Warbo

nix-daemon이 얼마나 흥미롭고 재미 있는지, 나는 그것에 관한 문제도 다루고 있습니다. nix-daemon이 특정 그룹의 사용자와의 연결을 끊는 이유가 궁금합니다. 이것이 보안 구성입니까? 또는 관련 : nixos.org/nix/manual/#idm140737318362784 ?
CMCDragonkai

커밋 메시지 에 따르면 "우연한"사용을 막는 것입니다. 내가 여기
Warbo

2

@mpontes '/ @ javier의 또 다른 수정은

ssh user@remoteserver -L 9999:localhost:9999 'socat TCP-LISTEN:9999,fork,bind=localhost UNIX-CONNECT:/var/run/mysqld/mysql.sock& pid=$!; trap "kill $pid" 0; while echo -ne " \b"; do sleep 5; done'

청소기

ssh user@remoteserver -L 9999:localhost:9999 '
  socat TCP-LISTEN:9999,fork,bind=localhost UNIX-CONNECT:/var/run/mysqld/mysql.sock&
  pid=$!
  trap "kill $pid" 0
  while echo -ne " \b"; do
    sleep 5
  done
'

찬성

  1. CentOS 7과 같은 6.7 이전의 openssh에서 작동
  2. 원격 서버로 다시 ssh하지 않고 ssh 종료시 socat을 종료합니다.
  3. 비공개 ssh 로그인 허용 (ijk 솔루션과 달리)

특색

  1. -f옵션을 사용하지 않기 때문에 공개 키를 사용하여 백그라운드에서 실행 &하거나 대화식으로 로그인하고 Ctrl + Z를 사용 $!하여 pid를 저장할 수 있습니다.

단점

  1. -f그런 식으로 ssh의 pid를 잃어 버리기 때문에 ssh 옵션을 쉽게 사용할 수 없습니다 . 이 방법은 포 그라운드에서 실행하고 Ctrl + C를 사용하여 종료합니다.
  2. 훨씬 더 복잡한

설명

  • socat ...& -원격 서버에서 백그라운드에서 socat을 실행하십시오.
  • pid=$! -pid를 저장
  • trap kill\ $pid 0kill $pid-bash 종료시 실행
  • while :; sleep... -무한 루프에 앉아
  • echo -ne \ \b-에코 공간과 백 스페이스가 뒤 따릅니다. ssh가 연결 해제되는 즉시 실패합니다. A를 sleep 5,이 수단을 그 socatssh를 5 초까지 실행할 수 있습니다

참고 : 실제로 고정 표시기, 포트 사용하여 테스트 2375, /var/run/docker.sock및 환경 변수를 DOCKER_HOST='tcp://localhost:2375'하지만, MySQL은 모두 같은 작동한다

최신 정보

사용 SSH 제어하는 것은 , 당신이 사용할 수있는 -f단지 다음과 같은 플래그를 추가, 내 방식을 사용하여 플래그를

-f -o ControlPath=~/.ssh/%C -o ControlMaster=auto

그리고 당신은 얻을 것이다

ssh -f -o ControlPath=~/.ssh/%C -o ControlMaster=auto user@remoteserver -L 9999:localhost:9999 'set -m; socat TCP-LISTEN:9999,fork,bind=localhost UNIX-CONNECT:/var/run/mysqld/mysql.sock& pid=$!; trap "kill $pid" 0; while echo -ne " \b"; do sleep 5; done'

이제 다음을 사용하여 모든 제어 된 세션을 종료 할 수 있습니다.

ssh -o ControlPath=~/.ssh/%C -O exit remoteserver

-o옵션은 저장할 수 있습니다 .ssh/config파일 또는 대신 -S를 사용할 수 있습니다 (하지만 당신은 필요 여전히거야 -o ControlMaster)


Docker 컨테이너 내부의 스크립트를 사용하여 다른 호스트에 코드를 배포하고 있습니다. 연결 논리는 훌륭하지만 bash 세션이 끝나면 끝납니다. 이로 인해 docker run ... connect.sh터널을 설정 한 다음 전화 를 걸지 못합니다 docker run ... deploy.sh. 나는 노력 nohup, &그리고 disown하지만 그들은 파괴하는 것 socat닫아 stdout과 트리거링 kill. 이 사건을 뒷받침하기 위해 조정에 대한 아이디어가 있습니까?
클레이 톤

승인. 이것은 실제로 터미널에서 잘 작동합니다 (w / -fand & disown). 분명히 문제는 스크립트 "래퍼"에 의해 생성됩니다. 의견을 환영하지만 지금보다 적절한 Q & A를보고 있습니다.
클레이 톤

@claytond 정확히 무엇을하고 있는지 확실하지는 않지만 컨테이너의 pid 1이 끝나면 다른 모든 명령이 종료됩니다. 배포 스크립트 시나리오에서 일반적으로하는 일은 "deploy"명령을 사용하고 컨테이너의 진입 점을 작성하는 것입니다. "if $ 1 (명령) == deploay then"이라고 표시되는 이미지는 ssh 명령과 deploy 명령을 실행 한 다음 종료하여 ssh 연결을 닫습니다. 또한 docker run ... connect.sh, 및 docker exec {container name/id} deploy.sh을 사용하여 함께 플레이 할 수도 있습니다.
앤디

네가 옳아. 실제로 exec이미 run컨테이너에서 사용하고 있으며 SSH 파이프가 exec끝난 후에도 지속되지 않았습니다 . 스크립트가 실행되는 방식에 문제가 있음을 분명히했습니다. 호출을 자체 스크립트로 이동 nohup <script.sh> & disown하고을 호출 하면의 완료 후에도 유지 exec됩니다.
클레이 톤

1

Javier의 답변을 자세히 설명하면 다음과 같이 작동합니다.

ssh -f xxx@yyy.zzz -L 9999:localhost:9999 "socat TCP-LISTEN:9999,fork,bind=localhost UNIX-CONNECT:/var/run/mysqld/mysql.sock"

당신이해야 할 fork첫 번째 연결을 종료하면 죽어 socat없이 여러 번 연결할 수 있어야하기 위해. 또한 socat을 사용하여 바인딩 할 주소를 지정하는 방법 bind은 포트 앞의 주소가 아니라 옵션을 통하는 것 입니다.

그런 다음 원하는 localhost:9999대로 정상적으로 연결하십시오 . 그런 다음 터널을 분해하십시오.

ssh -f xxx@yyy.zzz "killall socat"

(또는 비슷한 것, socat의 PID를 유지하는 것과 관련된보다 정교한 작업을 수행 할 수 있음)


1

예, socat을 사용할 수 있습니다.

먼저 SSH를 사용하여 TCP 터널을 수행하십시오. 그런 다음 socat을 다음과 같이 사용하십시오.

socat unix-listen : /var/run/mysqld/mysqld.sock, 포크, 링크 해제 초기 tcp : 127.0.0.1 : 3306

그런 다음 새로 작성된 소켓에 권한을 부여하십시오 (chmod 777이 가능할 수 있음).


OpenSSH 6.6부터 가능합니다.
ysdx

3
chmod 777: nonononono! 절대로 실행하지 마십시오 chmod 777. 실제로는 절대 필요하지 않습니다! "테스트 목적"도 아닙니다. 파일을 읽을 수 있으면 읽을 수 있습니다. 쓰기 권한이 user있거나 group쓰기가 필요한 경우 쓰기 가능합니다. 모든 사람에게 쓰기 권한을 부여 할 필요는 전혀 없으며, chmod다국적 기업이 해킹당하는 방식을 제정신으로 잊어 버리는 것입니다. 하지 마십시오. 이제까지. 유닉스 권한에 대한 소개를 썼습니다 . 읽어주세요!
Martin Tournoij
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.