포트 전달을 위해 제한된 SSH 사용자를 작성하는 방법은 무엇입니까?


106

ændrük 다른 사람과의 쉬운 SSH 연결을위한 역방향 연결제안했습니다 (원격 도움말). 작동하려면 연결을 수락하기 위해 추가 사용자가 필요합니다. 이 사용자는 서버를 통해 포트를 전달할 수 있어야합니다 (서버가 프록시 역할을 함).

위에서 설명한 것 이상을 수행 할 수없는 제한된 사용자를 어떻게 만듭니 까?

새로운 사용자는 있어야 하지 수 :

  • 쉘 명령을 실행
  • 파일에 액세스하거나 파일을 서버에 업로드
  • 서버를 프록시로 사용하십시오 (예 : webproxy)
  • 방화벽으로 인해 공개적으로 액세스 할 수 없었던 로컬 서비스에 액세스
  • 서버를 죽이다

요약하면, 권한없이 SSH 서버에만 연결할 수있는 제한된 SSH 사용자를 어떻게 작성하여 해당 컴퓨터와의 연결을 통해 연결할 수 있습니까?


답변:


166

TL; DR-답변의 맨 아래로 이동, "제한 적용"

제한된 사용자 추가는 다음 두 부분으로 구성됩니다. 1. 사용자 생성 2. SSH 데몬 (sshd) 구성

sshd 구성

SSH의 가능성을 알리는 가장 좋은 장소는 관련 매뉴얼 페이지를 읽는 것입니다.

SSH 클라이언트는 어디에서 작업을 수행 할 수 있습니까?

무언가를 제한하기 전에 SSH의 기능을 알아야합니다. 매뉴얼 페이지를 뱉으면 다음과 같은 결과가 나타납니다.

  • 쉘 명령 실행
  • sftp를 통한 파일 업로드
  • 포트 포워딩
    • 클라이언트는 (사용되지 않은) 포트를 서버로 전달합니다
    • 서버는 자신의 포트를 클라이언트에게 전달
    • 서버는 다른 호스트의 포트를 클라이언트에 전달합니다 (proxy-ish)
  • X11 포워딩 (디스플레이 포워딩)
  • 인증 에이전트 전달
  • 터널 장치의 전달

로부터 인증 의 섹션 SSHD (8)의 매뉴얼 페이지 :

클라이언트가 성공적으로 인증되면 세션 준비를위한 대화 상자가 입력됩니다. 이때 클라이언트는 의사 tty 할당, X11 연결 전달, TCP 연결 전달 또는 보안 채널을 통한 인증 에이전트 연결 전달 과 같은 것을 요청할 수 있습니다 .

그 후 클라이언트 는 쉘을 요청하거나 명령을 실행 합니다. 그러면 측면이 세션 모드로 들어갑니다. 이 모드에서 어느 한 쪽에서 언제든지 데이터를 보낼 수 있으며 이러한 데이터는 서버 쪽의 셸 또는 명령과 클라이언트 쪽의 사용자 터미널로 /로부터 전달됩니다.

SSH 기능 제한을위한 옵션

동작을 변경하는 파일 및 옵션은 다음과 같습니다.

  • ~/.ssh/authorized_keys -연결이 허용되는 키를 포함하며 옵션이 제공 될 수 있습니다.
    • command="command"-사용자가 제공 한 명령 (있는 경우)은 무시됩니다. 클라이언트는 명시 적으로 금지되지 않는 한 TCP 및 / 또는 X11 전달을 지정할 수 있습니다 . 이 옵션은 쉘, 명령 또는 서브 시스템 실행에 적용됩니다.
    • no-agent-forwarding -이 키가 인증에 사용될 때 인증 에이전트 전달을 금지합니다.
    • no-port-forwarding -이 키가 인증에 사용될 때 TCP 전달을 금지합니다
    • no-X11-forwarding - "이 키가 인증에 사용될 때 X11 전달을 금지합니다."
    • permitopen="host:port" -지정된 호스트 및 포트에만 연결할 수 있도록 로컬 'ssh -L'포트 전달을 제한하십시오.
  • ~/.ssh/environment-이 파일은 로그인시 환경으로 읽습니다 (있는 경우). 환경 처리는 기본적으로 비활성화되어 있으며 PermitUserEnvironment 옵션을 통해 제어됩니다.
  • ~/.ssh/rc -사용자의 홈 디렉토리에 액세스하기 전에 실행할 초기화 루틴이 포함되어 있습니다.
  • /etc/ssh/sshd_config -시스템 전체 구성 파일
    • AllowAgentForwarding -ssh-agent (1) 전달이 허용되는지 여부를 지정합니다.
    • AllowTcpForwarding
    • ForceCommand - "클라이언트가 제공 한 명령과 ~ / .ssh / rc가 있으면 명령을 무시하고 ForceCommand에 의해 지정된 명령을 강제 실행합니다. 명령은 -c 옵션과 함께 사용자의 로그인 쉘을 사용하여 호출됩니다."
    • GatewayPorts - "원격 호스트가 클라이언트에 전달 된 포트에 연결할 수 있는지 여부를 지정합니다. 기본적으로 sshd (8)는 원격 포트 전달을 루프백 주소에 바인딩합니다. 이는 다른 원격 호스트가 전달 된 포트에 연결하지 못하게합니다. GatewayPorts를 사용하여 지정할 수 있습니다. "sshd는 원격 포트 포워딩이 비 루프백 주소에 바인딩되어 다른 호스트가 연결될 수 있도록해야합니다."
    • PermitOpen:

      TCP 포트 전달이 허용되는 대상을 지정합니다. 전달 사양은 다음 형식 중 하나 여야합니다.

      PermitOpen host:port
      PermitOpen IPv4_addr:port
      PermitOpen [IPv6_addr]:port
      

      공백으로 구분하여 여러 개의 순방향을 지정할 수 있습니다. 'any'인수를 사용하면 모든 제한을 제거하고 전달 요청을 허용 할 수 있습니다. 기본적으로 모든 포트 전달 요청이 허용됩니다.

    • PermitTunnel-tun (4) 장치 전달 허용 여부를 지정합니다. 기본값은 '아니오'입니다
    • X11Forwarding-X11 전달이 허용되는지 여부를 지정합니다. 기본값은 '아니오'입니다

제한 사항 적용

시스템 전체 구성 파일을 수정 /etc/ssh/sshd_config하면 비밀번호 기반 인증이 적용되거나 제한 사항 ~/.ssh/authorized_keys이 실수로 제거 된 경우에도 구성을 적용 할 수 있습니다 . 전역 기본값을 수정 한 경우 그에 따라 옵션의 주석 처리를 제거해야합니다.

Match User limited-user
   #AllowTcpForwarding yes
   #X11Forwarding no
   #PermitTunnel no
   #GatewayPorts no
   AllowAgentForwarding no
   PermitOpen localhost:62222
   ForceCommand echo 'This account can only be used for [reason]'

이제 사용자를 추가하십시오 :

sudo useradd -m limited-user

ForceCommand쉘이 /bin/false(또는 /bin/true)와 같이 쉘이 아닌 것으로 설정되어 있으면 /bin/false -c [command]아무것도하지 않을 경우 옵션 을 생략 할 수 있습니다 .

이제 클라이언트는 SSH를 통해 서버의 루프백 주소에서 포트 62222에만 연결할 수 있습니다 (공용 IP 주소에서 수신 대기하지 않음)

비활성화 AllowTcpForwarding하면을 사용하지 못하게되어 -R단일 포트를 전달하기 위해 이러한 제한된 계정을 사용하지 못하게 됩니다. PermitOpen localhost:62222클라이언트가 서버에 행복하게 연결하고 청취 할 수 있기 때문에 서버의 포트 62222는 사용되지 않는 것으로 가정합니다.

시스템 전체 구성에서 TCP 전달이 허용되고 암호 기반 인증이 비활성화 된 경우 키별 설정도 사용할 수 있습니다. (옵션과 사이에 공백이있는) ~/.ssh/authorized_keys앞에 다음 옵션을 편집 하고 추가하십시오 .ssh-ssh-

command="echo 'This account can only be used for [reason]'",no-agent-forwarding,no-X11-forwarding,permitopen="localhost:62222"

검증

예상대로 작동하는지 확인하려면 일부 테스트 사례를 실행해야합니다. 아래 명령에서 host로 설정되지 않은 경우 실제 로그인으로 바꿔야합니다 ~/.ssh/config. 명령 뒤에 클라이언트 또는 서버 (지정된대로)에서 실행되어야하는 명령이 표시됩니다.

# connection closed:
ssh host
# connection closed (/bin/date is not executed):
ssh host /bin/date
# administratively prohibited (2x):
ssh host -N -D 62222 # client: curl -I --socks5 localhost:62222 example.com
ssh host -N -L 8080:example.com:80 # client: curl -I localhost:8080
sftp host
# should be possible because the client should forward his SSH server
ssh host -N -R 8080:example.com:80 # server: curl -I localhost:8080
# This works, it forwards the client SSH to the server
ssh host -N -R 62222:localhost:22
# unfortunately, the client can listen on that port too. Not a big issue
ssh host -N -L 1234:localhost:62222

결론

점검 목록 : SSH 사용자는 다음을 수행 할 수 없어야합니다.

  • 쉘 명령 실행- 완료
  • 파일에 액세스하거나 파일을 서버에 업로드- 완료
  • 서버를 프록시로 사용 (예 : webproxy)- 완료
  • 방화벽으로 인해 공개적으로 액세스 할 수없는 로컬 서비스에 액세스- 부분적으로 클라이언트는 62222 이외의 다른 포트에 액세스 할 수 없지만 서버에서 포트 62222를 수신하고 연결할 수 있음
  • - 서버 죽일 수행 (이러한 검사는 SSH 서버로 제한됩니다 메모를 사용하면 컴퓨터에 다른 취약한 서비스를 한 경우, 그것은 가능한 공격자가 명령을 실행할 수 있도록 서버를 죽이고, 등.)

3
이 기능을 사용하려면 추가 한 계정을 useradd잠금 해제해야합니다. 비밀번호를 /etc/shadow별표 ( *) 로 바꾸거나을 사용하여 비밀번호를 설정하면됩니다 sudo passwd limited-user.
Lekensteyn

2
SSH 서버가 sftp-server명령을 실행하기 때문에 SFTP가 작동합니다 . 를 사용 ForceCommand하면이 명령이 더 이상 실행되지 않습니다.
Lekensteyn

2
from=옵션 도 유용합니다 authorized_keys. 특정 IP 주소 또는 호스트 이름을 가진 소스로 키 사용을 제한 할 수 있습니다. 예, from="1.1.1.1"또는 from="10.0.0.?,*.example.com". authorized_keys 옵션 에 대해서는 매뉴얼 페이지 ( linux.die.net/man/8/sshd )의 "AUTHORIZED_KEYS FILE FORMAT"섹션을 참조하십시오 .
Donn Lee

2
"AllowTcpForwarding local"은 원격 전달을 금지합니다. (이 답변이 쓰여졌을 때 그것이 존재했는지는 모르겠습니다.)
Simon Sapin

1
이것은 지속적인 SSH 연결에 의해 상처 입는 있습니다, 그래서 당신은 같은 것을하지 말았어야 Host * ControlMaster auto당신에 ~/.ssh/config와 연결할 때 파일 ssh -N. 필요한 경우ssh -N -o ControlMaster=no
nh2

3

나는 이것에 대한 많은 해결책이 있으며, 내가 제안하는 것보다 훨씬 더 강력하다고 확신합니다. 그러나 이것은 귀하의 필요에 충분할 수 있습니다. 이를 위해 사용자가 ssh 키 기반 인증을 수행 할 수 있다고 가정합니다 (퍼티 또는 유닉스 ssh가 이것을 지원해야 함).

  • 평소처럼 사용자 추가 ( 'adduser'또는 기타 도구)

  • 사용자 .ssh dir 및 .ssh / authorized_keys를 작성하십시오.

your_user $ sudo -Hu ssh_forwarder /bin/bash

ssh_forwarder $ cd ~
ssh_forwarder $ mkdir .ssh
ssh_forwarder $ ( umask 066 && cat > .ssh/authorized_keys ) <<EOF
no-agent-forwarding,no-X11-forwarding,command="read a; exit" ssh-rsa AAAB3NzaC1y....2cD/VN3NtHw== smoser@brickies
EOF
  • 이 계정에 대한 비밀번호 액세스를 비활성화하십시오.
your_user $ sudo usermod --lock ssh_forwarder

이제 사용자가 시스템에 액세스 할 수있는 유일한 방법은 적절한 ssh 키에 액세스하는 것입니다. ssh는 실행하려는 시도에 상관없이 "/ bin / bash -c 'read a'"를 실행합니다. 'read a'는 개행까지 읽은 다음 쉘이 종료되므로 사용자는 'enter'를 눌러 연결을 끊어야합니다.

'command ='에서 할 수있는 다른 많은 것들이 있습니다. 자세한 man authorized_keys정보는 'command'를 참조하십시오.

Enter 키를 누르면 연결이 끊어진다는 사실이 마음에 들지 않으면 'command ='항목에 다음과 같은 것을 사용할 수 있습니다.

command="f=./.fifo.$$ && mkfifo $f && trap \"rm -f $f\" EXIT && read a <$f && echo $a; exit;"

이것은 단지 사용자 홈 디렉토리에 임시 fifo를 생성 한 다음 읽습니다. 해당 파일에 아무것도 쓰지 않으므로 무한정 중단됩니다. 또한 해당 연결을 강제로 종료하려는 경우 다음과 같은 작업을 수행 할 수 있습니다.

 your_user$ echo GOODBYE | sudo tee ~ssh_forwarder/.fifo.*

이것은 아주 적은 리소스를 사용해야하며, 쉘 종료로 끝나지 않는 스크립트에서 아무것도 잘못 될 수 없습니다.

sleep 1h; echo You have been here too long. Good bye.

사용자가 원격으로 전달 ( ssh -R)하지만 제한 ( ssh -L) 하는 방법을 직접 보지 못했습니다 . 아마도 'permitopen'이 사용될 수 있습니다. 인터넷 검색 은 그다지 도움이되지 않았습니다. 'no-port-forwarding, permitremoteopen = 10001'과 같은 것이 허용하는 데 도움이 될 것 같습니다 ssh -R 6901:localhost:6901.

이다 솔루션입니다. 가장 확실하게 향상 될 수 있으며 원격 포트를 열 때마다 면밀히 조사해야합니다. 나의 목표가 할머니가 내 LAN에 연결하도록 허용하여 vnc를 사용하여 화면을 볼 수 있고 해당 키에 대한 액세스가 그녀에게 제한되어 있다면 개인적으로 합리적으로 안전하다고 느낄 것입니다. 이것이 기업을위한 것이면 더 철저한 조사가 필요할 것입니다. 알아야 할 것은 쉘을 전혀 요청하지 않으므로 'command ='코드가 실행되지 않는다는 것입니다.ssh -N

더 안전한 다른 메커니즘으로는 사용자를위한 사용자 지정 셸을 만들고 심지어이를 의류로 잠그는 것도 포함될 수 있습니다.


3
이것은 매우 해킹처럼 보이므로 명령을 실행할 필요가 없으므로 쉘을 가질 필요조차 없습니다. 참조 의 매뉴얼 페이지를ssh 에 대한 -N옵션을 선택합니다. 이를 달성하는 더 확실한 방법이 있어야합니다.
Lekensteyn

사실입니다. 나는 또한 더 깨끗한 해결책을 기대하고 있습니다. 'permitremoteopen'옵션이 있으면 포트 없음 전달과 함께 authorized_keys가 꽤 좋은 해결책이라고 생각합니다.
smoser

나는 researcg를했습니다 (위 참조). ssh -N명령을 전혀 실행하지 않기 때문에 command="something"세션 을 닫는 데 아무런 문제가 없습니다 .
Lekensteyn

뭔가 빠졌습니까? 그것이 필요한 전부인 것 같았 chsh ssh_forwarder -s /bin/false 습니다.
typelogic
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.