Jak utworzyć ograniczonego użytkownika SSH do przekierowania portów?

106

ændrük zasugerował połączenie odwrotne w celu uzyskania łatwego połączenia SSH z kimś innym (w celu uzyskania pomocy zdalnej). Aby to zadziałało, potrzebny jest dodatkowy użytkownik, aby zaakceptować połączenie. Ten użytkownik musi mieć możliwość przekazania swojego portu przez serwer (serwer działa jako serwer proxy).

Jak utworzyć użytkownika z ograniczonym dostępem, który nie może zrobić nic więcej niż wyżej opisane?

Nowy użytkownik nie może być w stanie:

  • wykonać polecenia powłoki
  • uzyskiwać dostęp do plików lub przesyłać pliki na serwer
  • użyj serwera jako proxy (np. webproxy)
  • uzyskać dostęp do lokalnych usług, które w innym przypadku nie byłyby publicznie dostępne z powodu zapory ogniowej
  • zabij serwer

Podsumowując, w jaki sposób mogę utworzyć użytkownika SSH z ograniczeniami, który będzie mógł łączyć się tylko z serwerem SSH bez uprawnień, aby można było łączyć się przez to połączenie z jego komputerem?

Lekensteyn
źródło

Odpowiedzi:

166

TL; DR - przejdź do dołu odpowiedzi „Stosowanie ograniczeń”

Dodanie ograniczonego użytkownika składa się z dwóch części: 1. Tworzenie użytkownika 2. Konfigurowanie demona SSH (sshd)

Konfigurowanie sshd

Najlepszym miejscem na zapoznanie się z możliwościami SSH jest przeczytanie powiązanych stron podręcznika:

Gdzie klient SSH może wykonywać działania?

Aby móc coś ograniczyć, musisz poznać funkcje SSH. Przejrzenie stron podręcznika daje:

  • Wykonywanie poleceń powłoki
  • Przesyłanie pliku przez sftp
  • Przekierowanie portów
    • Klient przekazuje (nie) używany port do serwera
    • Serwer przekazuje swój port do klienta
    • Serwer przekazuje port innego hosta do klienta (proxy)
  • Przekazywanie X11 (przekazywanie wyświetlacza)
  • Przekazywanie agenta uwierzytelniania
  • Przekazywanie urządzenia tunelowego

W sekcji Uwierzytelnianie strony podręcznika sshd (8) :

Jeśli klient pomyślnie się uwierzytelni, pojawi się okno dialogowe przygotowania sesji. W tej chwili klient może zażądać przydzielenia pseudo-tty, przekierowania połączeń X11, przekierowania połączeń TCP lub przekierowania połączenia agenta uwierzytelniania za pośrednictwem bezpiecznego kanału.

Następnie klient albo żąda powłoki, albo wykonania polecenia . Strony następnie wchodzą w tryb sesji. W tym trybie każda ze stron może wysyłać dane w dowolnym momencie, a dane te są przekazywane do / z powłoki lub polecenia po stronie serwera, a terminal użytkownika po stronie klienta.

Opcje ograniczenia funkcji SSH

Pliki i ich opcje zmieniające zachowanie to:

  • ~/.ssh/authorized_keys - zawiera klucze, które można połączyć, które mogą mieć opcje:
    • command="command"- Polecenie dostarczone przez użytkownika (jeśli istnieje) jest ignorowane. Pamiętaj, że klient może określić przekazywanie TCP i / lub X11, chyba że jest to wyraźnie zabronione . Zauważ, że ta opcja dotyczy wykonania powłoki, polecenia lub podsystemu.
    • no-agent-forwarding - Zabrania przekazywania agenta uwierzytelniania, gdy ten klucz jest używany do uwierzytelniania.
    • no-port-forwarding - Zabrania przekazywania TCP, gdy ten klucz jest używany do uwierzytelniania
    • no-X11-forwarding - „Zabrania przekazywania X11, gdy ten klucz jest używany do uwierzytelniania”.
    • permitopen="host:port" - Ogranicz przekierowywanie lokalnego portu „ssh -L”, tak aby mógł on łączyć się tylko z określonym hostem i portem.
  • ~/.ssh/environment- Ten plik jest wczytywany do środowiska przy logowaniu (jeśli istnieje). Przetwarzanie środowiska jest domyślnie wyłączone i jest kontrolowane za pomocą opcji PermitUserEnvironment
  • ~/.ssh/rc - Zawiera procedury inicjalizacji, które należy uruchomić, zanim katalog osobisty użytkownika stanie się dostępny.
  • /etc/ssh/sshd_config - ogólnosystemowy plik konfiguracyjny
    • AllowAgentForwarding - Określa, czy dozwolone jest przekazywanie ssh-agent (1).
    • AllowTcpForwarding
    • ForceCommand - „Wymusza wykonanie polecenia określonego przez ForceCommand, ignorując każde polecenie dostarczone przez klienta i ~ / .ssh / rc, jeśli jest obecne. Polecenie jest wywoływane przy użyciu powłoki logowania użytkownika z opcją -c.”
    • GatewayPorts - "Określa, czy zdalne hosty mogą łączyć się z portami przekierowanymi dla klienta. Domyślnie sshd (8) wiąże przekazywanie portów zdalnych z adresem pętli zwrotnej. Zapobiega to łączeniu się innych portów z portami przekierowanymi. GatewayPorts może być użyty do określenia że sshd powinien umożliwiać zdalne przekierowanie portów na adresy niezwiązane z pętlą zwrotną, umożliwiając w ten sposób łączenie się innych hostów. ”
    • PermitOpen:

      Określa miejsca docelowe, do których dozwolone jest przekierowanie portów TCP. Specyfikacja przesyłania musi mieć jedną z następujących postaci:

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

      Można podać wiele przekazów, oddzielając je spacjami. Argument „dowolny” może zostać wykorzystany do usunięcia wszystkich ograniczeń i zezwalania na wszelkie żądania przekazywania. Domyślnie wszystkie żądania przekierowania portów są dozwolone.

    • PermitTunnel- Określa, czy dozwolone jest przekazywanie urządzeń tun (4). Domyślnie jest to „nie”
    • X11Forwarding- Określa, czy dozwolone jest przekazywanie X11. Domyślnie jest to „nie”

Stosowanie ograniczeń

Modyfikacja ogólnosystemowego pliku konfiguracyjnego /etc/ssh/sshd_configumożliwia zastosowanie konfiguracji, nawet jeśli zastosowano uwierzytelnianie oparte na haśle lub przypadkowe usunięcie ograniczeń ~/.ssh/authorized_keys. Jeśli zmodyfikowałeś globalne ustawienia domyślne, odpowiednio odkomentuj opcje.

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]'

Teraz dodaj użytkownika:

sudo useradd -m limited-user

Opcję tę ForceCommandmożna pominąć, jeśli powłoka jest ustawiona na powłokę inną niż shell, jak /bin/false(lub /bin/true), ponieważ /bin/false -c [command]nic nie zrobi.

Teraz klient może połączyć się tylko z portem 62222 na adresie zwrotnym serwera przez SSH (nie będzie nasłuchiwał na publicznym adresie IP)

Wyłączenie AllowTcpForwardinguniemożliwiłoby również użycie -R, a tym samym pokonanie korzystania z takiego ograniczonego konta do przekazywania pojedynczego portu. PermitOpen localhost:62222zakłada, że ​​port 62222 na serwerze nigdy nie jest używany, ponieważ klient może z radością się z nim połączyć i nasłuchiwać.

Jeśli przekazywanie TCP jest dozwolone w konfiguracji ogólnosystemowej i wyłączone uwierzytelnianie oparte na hasłach, możesz również użyć ustawień dla poszczególnych kluczy. Edytuj ~/.ssh/authorized_keysi dodaj kolejne opcje przed ssh-(ze spacją między opcjami i ssh-):

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

Zweryfikować

Aby mieć pewność, że działa zgodnie z oczekiwaniami, należy uruchomić niektóre przypadki testowe. W poniższych poleceniach hostnależy zastąpić rzeczywistym logowaniem, jeśli nie jest ustawione ~/.ssh/config. Za poleceniem znajduje się polecenie, które powinno zostać wykonane na kliencie lub serwerze (jak określono).

# 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

Wniosek

Lista kontrolna: użytkownik SSH nie powinien:

  • wykonywanie poleceń powłoki - gotowe
  • dostęp do plików lub przesyłanie plików na serwer - gotowe
  • użyj serwera jako proxy (np. webproxy) - gotowe
  • uzyskać dostęp do lokalnych usług, które w innym przypadku nie byłyby publicznie dostępne z powodu zapory - częściowo klient nie może uzyskać dostępu do portów innych niż 62222, ale może nasłuchiwać i łączyć się z portem 62222 na serwerze
  • zabij serwer - gotowe (pamiętaj, że te kontrole są ograniczone do serwera SSH. Jeśli masz inną wrażliwą usługę na komputerze, może to umożliwić potencjalnemu atakującemu uruchomienie poleceń, zabicie serwera itp.)
Lekensteyn
źródło
3
Aby to zadziałało, konto dodane przez useraddmusi być odblokowane. Można to zrobić, zastępując hasło /etc/shadowgwiazdką ( *) lub ustawiając hasło za pomocą sudo passwd limited-user.
Lekensteyn
2
SFTP działa, ponieważ serwer SSH uruchamia sftp-serverpolecenie. Za pomocą ForceCommandtego polecenia nie będzie już wykonywane.
Lekensteyn,
2
Przydatna jest również from=opcja w authorized_keys. Pozwala ograniczyć użycie klucza do źródeł o określonym adresie IP lub nazwie hosta. Przykład from="1.1.1.1"lub from="10.0.0.?,*.example.com". Zobacz sekcję „FORMAT PLIKU AUTORYZOWANEGO KLUCZA ” na stronie podręcznika ( linux.die.net/man/8/sshd ), aby uzyskać informacje na temat wszystkich opcji kluczy autoryzowanych.
Donn Lee
2
„AllowTcpForwarding local” zabrania zdalnego przekazywania. (Nie wiem, czy istniała, kiedy napisano tę odpowiedź.)
Simon Sapin,
1
Zauważ, że jest to przerywane przez trwałe połączenia ssh, więc nie powinieneś mieć czegoś takiego Host * ControlMaster autow swoim ~/.ssh/configpliku podczas łączenia ssh -N. Jeśli potrzebujesz, użyjssh -N -o ControlMaster=no
nh2 10.04.17
3

Jestem pewien, że istnieje wiele rozwiązań tego problemu i wiele bardziej niezawodnych niż to, które proponuję. Może to jednak wystarczyć dla twoich potrzeb. Aby to zrobić, zakładam, że użytkownik jest w stanie przeprowadzić uwierzytelnianie oparte na kluczu ssh (kit lub jakikolwiek ssh unix powinien to obsługiwać).

  • Dodaj użytkownika w normalny sposób („adduser” lub inne narzędzie)

  • Utwórz użytkowników .ssh dir i .ssh / Author_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
  • Wyłącz dostęp do tego konta hasłem.
your_user $ sudo usermod --lock ssh_forwarder

Teraz jedynym sposobem, w jaki użytkownik może dostać się do twojego systemu, jest dostęp do odpowiedniego klucza ssh, a ssh uruchomi dla nich „/ bin / bash -c 'odczytać'”, bez względu na to, co spróbują uruchomić. „czytaj a” będzie po prostu czytać aż do nowej linii, a następnie powłoka wyjdzie, więc użytkownik musi tylko nacisnąć „enter”, aby zabić połączenie.

Jest wiele innych rzeczy, które możesz zrobić w 'command ='. Zobacz man authorized_keysi wyszukaj „polecenie”, aby uzyskać więcej informacji.

Jeśli nie podoba ci się fakt, że naciśnięcie Enter zabija połączenie, możesz użyć czegoś takiego jak poniżej dla wpisu „command =”:

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

To tylko tworzy tymczasowe fifo w katalogu domowym użytkowników, a następnie próbuje je odczytać. Do tego pliku nic nie zapisze, więc zawiesi się ono na czas nieokreślony. Dodatkowo, jeśli chcesz siłą zakończyć połączenie, możesz zrobić coś takiego:

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

To powinno zużywać bardzo mało zasobów i nic nie powinno się nie udać w tym skrypcie, które nie kończy się na zakończeniu powłoki.

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

Nie widziałem, jak można pozwolić użytkownikowi na zdalne przekazywanie dalej ( ssh -R), ale limit ( ssh -L). Być może można by użyć „permopen”. Googling nie był zbyt pomocny. Wydawać by się mogło, że coś takiego jak „bez przekierowania portów, permémoteopen = 10001” byłoby przydatne, aby na to pozwolić ssh -R 6901:localhost:6901.

To rozwiązanie. Można to zdecydowanie poprawić, a każde otwarcie zdalnych portów powinno być sprawdzone. Gdyby moim celem było zezwolenie mojej Babci na połączenie się z moją siecią LAN, abym mógł użyć vnc do wyświetlenia jej ekranu, a dostęp do tych kluczy byłby ograniczony do niej, osobiście czułbym się dość bezpiecznie. Gdyby tak było w przypadku przedsiębiorstwa, konieczne byłoby dokładniejsze dochodzenie. Należy pamiętać, że wcale nie żąda powłoki, więc kod „command =” nie jest wykonywany.ssh -N

Inne, być może bardziej bezpieczne mechanizmy mogą obejmować tworzenie niestandardowej powłoki dla użytkownika, a nawet blokowanie jej za pomocą aparatu.

smoser
źródło
3
Wygląda to bardzo hackersko, nawet nie trzeba mieć powłoki, ponieważ nie trzeba wykonywać żadnych poleceń. Zobacz stronę instrukcjissh dla -Nopcji. Musi istnieć czystszy sposób na osiągnięcie tego.
Lekensteyn,
To prawda. Mam nadzieję, że zobaczę też czystsze rozwiązanie. Sądzę, że klucze autoryzowane w połączeniu z przekierowaniem bez portu byłyby całkiem dobrym rozwiązaniem, gdyby istniała opcja „allowremoteopen”.
smoser
Zrobiłem trochę badań (patrz wyżej). Ponieważ w ssh -Nogóle nie wykonuje polecenia, nie ma problemu z command="something"zamknięciem sesji.
Lekensteyn
Czy coś mi brakuje? Wydawało się, że chsh ssh_forwarder -s /bin/false to wszystko.
typelogiczny