RE:NODE

SFTP permission denied: připojíš se, ale soubory nejdou upravit

Text: Tým RE:NODE
15 min čtení


Pokud se tvůj SFTP klient přihlásí, vypíše složky a bez problémů stáhne soubory, ale každé uložení, nahrání nebo smazání skončí hláškou Permission denied, problém není v přihlášení. Autentizace proběhla. Selhala až další kontrola: operační systém (nebo SFTP služba panelu) rozhoduje, jestli uživatel, jako kterého jsi přihlášený, smí zapisovat do konkrétního souboru nebo do složky, která ho obsahuje. Na stroji, který spravuješ sám, je příčinou téměř vždy vlastnictví - soubory patří uživateli služby nebo root a ty jsi přihlášený jako někdo jiný. Na herním panelu je příčinou téměř vždy oprávnění v panelu, chráněný soubor nebo plný disk. Řešením nikdy není chmod 777.

Tento článek prochází příčiny v pořadí, v jakém se v praxi objevují, s příkazem, který každou z nich potvrdí, a s opravou, která nevyrobí nový problém. Práva k souborům a spustitelný bit jsou podrobně popsané v článku práva a vlastnictví souborů herního serveru; tady jde o konkrétní situaci, kdy jsi připojený a přesto nemůžeš zapisovat.

Čtení funguje, zápis ne: proč#

SFTP není samostatný systém oprávnění. Na běžném linuxovém serveru běží sftp-server z OpenSSH (nebo internal-sftp) jako uživatel, jako kterého ses přihlásil, a každá operace se souborem je obyčejné systémové volání provedené pod tímto uživatelem. Pokud alice nemůže soubor zapsat v shellu, nemůže ho zapsat ani přes SFTP. SFTP klient jen hlásí, co řeklo jádro.

Čtení vyžaduje mnohem méně než zápis. Ke stažení server.properties potřebuješ r na souboru a x na každé složce nad ním. Ke změně souboru potřebuješ w na souboru. K nahrání nového souboru, smazání nebo přejmenování potřebuješ w a x na složce, bez ohledu na práva samotného souboru. Právě kvůli této asymetrii se tak často objevuje hlášení „vidím všechno, ale nic nemůžu změnit“: výchozí práva jsou 644 pro soubory a 755 pro složky, což všem kromě vlastníka dává přesně tohle - číst, vypsat, stáhnout, nic víc.

Nejdřív se ujisti, že jde o chybu zápisu, a ne o chybu přihlášení. Jsou to dva různé problémy:

code
Permission denied (publickey,password).          <- login failed, see SSH keysError: /srv/game/server.properties: open for write: permission deniedremote open("/srv/game/start.sh"): Permission deniedCouldn't open for writing

První řádek znamená, že ses vůbec nepřihlásil, a pro to je určený článek SSH permission denied (publickey). Vše níže se týká zbylých tří, které znamenají totéž: přihlášen, ale odmítnut u jednoho souboru nebo jedné složky. Přesné znění závisí na klientovi; FileZilla hlásí open for write: permission denied, klient sftp z OpenSSH hlásí remote open(...) nebo dest open a pluginy do editorů obvykle napíšou, že soubor nešlo otevřít pro zápis.

Komu soubor patří a kdo jsi ty#

Na téměř každý případ stačí odpovědět dvěma příkazy. Přes SSH nebo z promptu sftp se podívej na soubor a jeho složku:

bash
$ ls -la /srv/game/drwxr-xr-x  5 steam steam 4096 Oct 14 20:10 .-rw-r--r--  1 steam steam 1843 Oct 14 20:11 server.properties-rw-r--r--  1 root  root   612 Oct 12 09:02 mods.json$ iduid=1001(alice) gid=1001(alice) groups=1001(alice)

Čti to jako větu. Složka patří uživateli steam a zapisovat do ní smí jen steam. server.properties patří uživateli steam a změnit ho smí jen steam. mods.json patří uživateli root, takže ho nesmí změnit ani steam. A ty jsi alice, který není ani jeden z nich, takže se na tebe vztahují jen poslední tři bity: r-x na složce, r-- na souborech. Jen pro čtení, přesně jak jsi pozoroval.

Grafické klienty ukazují stejné sloupce. Ve FileZille má vzdálený panel sloupce Permissions a Owner/Group; ve WinSCP jsou ve vzdáleném panelu a ve vlastnostech souboru. Pokud sloupec vlastníka ukazuje číslo místo jména (988, 1000), klient prostě k danému id nezná jméno - vlastnictví je přesto skutečné.

Tabulka níže shrnuje, co potřebuješ pro jednotlivé operace. Všimni si, jak často je důležitější složka než soubor:

ChcešNa souboruNa složce
Stáhnoutrx (a r pro výpis)
Upravit a uložit na místěwx
Nahrát nový soubor-w a x
Smazat nebo přejmenovatnicw a x
Uložit přes dočasný soubor-w a x

Poslední řádek je místo, kde editory lidi nachytají, a proto má níže vlastní sekci.

Soubory vytvořené službou nebo rootem#

Na VDS nebo domácím serveru to obvykle vypadá takhle. Hra, webová aplikace nebo bot běží pod vyhrazeným uživatelem služby - steam, www-data, minecraft. Ty se přihlásíš přes SFTP jako svůj vlastní uživatel, abys upravil její konfiguraci. Tvůj uživatel může číst všechno (soubory mají 644) a nic zapisovat. Nebo jsi to jednou opravil a vrátilo se to, protože služba pořád vytváří nové soubory se svým vlastníkem a umaskem 022. Nebo někdo spustil aktualizaci přes sudo a teď několik souborů patří uživateli root a nezvládne je změnit ani samotná služba.

Existují tři rozumné opravy a to, která je správná, závisí na tom, komu mají data patřit.

Přihlas se jako uživatel služby. Nejjednodušší možnost, když server spravuje jediný člověk. Dej uživateli služby SSH klíč (ne heslo) a připojuj se jako on. Všechno, co nahraješ, pak má správného vlastníka od začátku. U uživatele herního serveru je to v pořádku; nedělej to u www-data ani u jiného účtu, který systém sdílí mezi více službami.

Sdílej skupinu. Když potřebují zapisovat člověk i služba, dej je do společné skupiny a nastav celý strom jako zapisovatelný pro skupinu:

bash
# a group for everyone who edits this server$ sudo groupadd gameadmins$ sudo usermod -aG gameadmins alice$ sudo usermod -aG gameadmins steam# hand the tree to the service user and the shared group$ sudo chown -R steam:gameadmins /srv/game$ sudo chmod -R g+rwX /srv/game# new files inside inherit the group, not the creator's own group$ sudo find /srv/game -type d -exec chmod g+s {} +

Velké X v g+rwX přidá právo spouštění jen složkám a souborům, které ho už měly, takže z každé konfigurace nevyrobí spustitelný soubor. Bit g+s (setgid) na složkách znamená, že vše, co v nich vznikne, patří skupině gameadmins, a ne tomu, kdo to vytvořil. Členství ve skupině se čte při přihlášení, takže se alice musí odpojit a znovu připojit, než se to projeví - krok, který zdržuje překvapivě často.

Setgid opraví skupinu, ne práva. Pokud služba dál vytváří soubory s 644, budou ve správné skupině, ale nebudou zapisovatelné pro skupinu. Nastav službě umask 002: u jednotky systemd je to UMask=0002 v sekci [Service], následované systemctl daemon-reload a restartem. Pro soubory, které nahráváš, ti OpenSSH umožňuje nastavit umask samotné SFTP relace pomocí ForceCommand internal-sftp -u 0002 nebo Subsystem sftp internal-sftp -u 0002 v sshd_config.

Použij ACL, když se model se skupinami stane nepřehledným (několik služeb, každá s vlastním stromem). Výchozí ACL na složce se uplatní na všechno, co v ní později vznikne:

bash
$ sudo setfacl -R -m u:alice:rwX /srv/game$ sudo setfacl -R -d -m u:alice:rwX /srv/game$ getfacl /srv/game/server.properties

ACL se v ls -l projeví jako + na konci práv (-rw-rw-r--+) a mnoho SFTP klientů je nezobrazuje vůbec, což stojí za zapamatování, když viditelná práva zdánlivě odporují tomu, co se skutečně děje.

Co nedělat: chmod -R 777. Udělá z každého souboru zapisovatelný soubor pro každý účet i každý napadený proces na stroji a navíc nepřežije, až služba vytvoří další soubor. Druhá špatná oprava, spouštění služby jako root, aby mohla „zapisovat cokoli“, je rozebraná v sekci o vlastnictví v článku o právech a stručně: zranitelný plugin pak ovládne celý stroj. Více herních serverů na jednom VDS popisuje uspořádání s jedním uživatelem na server, díky kterému je to celé předvídatelné.

Chroot SFTP: složka, do které se dostaneš, není tvoje#

Chrootované SFTP je běžné na sdíleném a ručně sestaveném hostingu: uživatel je zamčený v jedné složce a zbytek systému nevidí. Obvyklá konfigurace vypadá takhle:

/etc/ssh/sshd_config
Match User alice    ChrootDirectory /srv/sftp/alice    ForceCommand internal-sftp    AllowTcpForwarding no    X11Forwarding no

OpenSSH trvá na tom, aby chrootová složka i každá složka nad ní patřily uživateli root a nebyly zapisovatelné pro žádného jiného uživatele ani skupinu. Pokud jsou, přihlášení selže a log autentizace na serveru uvede bad ownership or modes for chroot directory. Důsledkem je klasická chrootová stížnost: uživatel se přihlásí, ocitne se v / a nemůže nic nahrát, protože / uvnitř vězení je složka patřící rootovi, do které nesmí zapisovat - záměrně.

Oprava je zapisovatelná podsložka uvnitř vězení:

bash
$ sudo chown root:root /srv/sftp/alice$ sudo chmod 755 /srv/sftp/alice$ sudo mkdir /srv/sftp/alice/upload$ sudo chown alice:alice /srv/sftp/alice/upload

Uživatelé pak zapisují do /upload. Pokud se soubory mají dostat do skutečné složky aplikace, použij bind mount místo symlinku - symlink mířící mimo vězení se vyhodnotí uvnitř něj a nikam nevede.

Připojení jen pro čtení, plné disky a neměnné soubory#

Někdy jsou práva v pořádku, vlastník je v pořádku a zápis přesto selhává. Tři příčiny leží úplně pod úrovní práv.

Souborový systém jen pro čtení. Chyba zní Read-only file system (EROFS), i když ji někteří SFTP klienti zploští na obecné selhání nebo dokonce na permission denied. Zkontroluj volby připojení:

bash
$ findmnt -no OPTIONS --target /srv/gamero,relatime

Svazek může být připojený jako ro záměrně (síťové úložiště, ISO, svazek kontejneru připojený jen pro čtení), ale souborový systém, který včera byl zapisovatelný a dnes je ro, obvykle znamená, že ho jádro po zjištění chyby disku připojilo znovu jen pro čtení. To je problém hardwaru nebo hostitele, ne nastavení; podívej se do dmesg a přestaň na něj zapisovat, dokud nepochopíš, co se stalo.

Plný disk nebo došlé inody. Zápis selže, když není místo, a mnoho klientů to hlásí špatně - useknuté nahrání, soubor s nulovou velikostí po uložení nebo nejasná chyba místo No space left on device. Zkontroluj bajty i inody:

bash
$ df -h /srv/game$ df -i /srv/game

Na ext4 je tu háček: asi 5 % bloků je ve výchozím stavu vyhrazeno pro root. Při zaplnění na 96 % může proces roota ještě zapisovat, zatímco tvůj uživatel ne, což vypadá přesně jako problém s právy. Plný disk herního serveru popisuje, jak zjistit, co ho zaplnilo.

Neměnný soubor. chattr +i udělá soubor nezměnitelným i pro root a chyba zní Operation not permitted. Někteří admini to používají, aby hra nepřepisovala konfiguraci, a pak na to zapomenou. Zkontroluj a zruš to v shellu:

bash
$ lsattr /srv/game/server.properties----i---------e------- /srv/game/server.properties$ sudo chattr -i /srv/game/server.properties

Na distribucích se zapnutým SELinuxem (Fedora, RHEL a jeho přebuildy) je ještě jedna vrstva: soubor se špatným bezpečnostním kontextem může být odmítnut, i když to práva dovolují. ls -Z ukáže kontext a obvyklými viníky jsou soubory, které byly na místo přesunuty, a ne zkopírovány.

Editory, které ukládají přes dočasný soubor#

Častý a matoucí případ: soubor můžeš přepsat nahráním, ale uložení z editoru selže, nebo naopak. Důvod je, že „uložit“ není jedna operace. Mnoho nástrojů zapíše nový soubor vedle původního a pak ho přejmenováním přepíše, aby přerušené spojení nemohlo zanechat napůl zapsanou konfiguraci. K tomu je potřeba w na složce. Pokud máš zápis na soubor, ale ne na jeho složku, zápis na místě uspěje a uložení přes dočasný soubor selže.

WinSCP to u nahrávání dělá ve výchozím stavu: soubor se přenáší jako name.filepart a po dokončení se přejmenuje. Volba je v Preferences, Transfer, Endurance jako „Enable transfer resume/transfer to temporary filename“. Nastavení na Disable způsobí, že WinSCP zapisuje přímo do cílového souboru, což funguje, když je zapisovatelný jen soubor. WinSCP se také po nahrání pokouší nastavit práva a časové razítko; když smí soubor zapsat, ale ne změnit jeho atributy, ohlásí, že nahrání uspělo, ale nastavení práv nebo časového razítka selhalo. Nahrání ve skutečnosti proběhlo. V nastavení přenosu je volba „Ignore permission errors“, případně pro dané připojení odškrtni „Set permissions“ a „Preserve timestamp“.

FileZilla zapisuje na místě, takže problém s dočasným souborem se tu objevuje zřídka; její „View/Edit“ stáhne lokální kopii a po uložení ji nahraje zpět, což je obyčejné nahrání s obyčejnými pravidly. Pokud FileZilla ukáže open for write: permission denied, soubor nebo jeho složka opravdu není pro tvého uživatele zapisovatelná.

Rozšíření do editorů a jiné nástroje se liší. SFTP rozšíření pro VS Code, pluginy do Notepad++ i připojení přes sshfs mají každé vlastní strategii a některé se při uložení snaží zachovat původní práva souboru. Pokud na stejném souboru funguje jeden nástroj a druhý ne, předpokládej rozdíl v dočasném souboru nebo atributech dřív, než předpokládáš, že se změnil server.

Existuje i past opačným směrem: klient nastavený tak, aby při nahrání aplikoval pevná práva, může potichu měnit práva souborů. Pokud skript při každém nahrání ztratí bit spustitelnosti, hledej příčinu v nastavení práv při nahrávání v klientovi, ne na serveru.

Na herním panelu ve stylu Pterodactylu#

Panely postavené na Pterodactylu a Wings nepoužívají k přístupu k souborům OpenSSH. Wings provozuje vlastní SFTP službu, k uživatelskému jménu se připojuje krátké id serveru (alice.1a2b3c4d), port je obvykle 2022 místo 22 a za ním není žádný shell. Každý soubor patří jedinému neprivilegovanému uživateli, pod kterým běží kontejner serveru - tomu, který se ve výpisech zobrazuje jako container - a cokoli nahraješ, dostane tohoto vlastníka automaticky. Problém se soubory od roota a problém „uživatel služby vs. můj uživatel“ tu tedy nevzniká. chown není dostupný a není ho potřeba; chmod funguje pro nastavení práv jako 755 na skriptu.

Když zápis na panelu selhává, příčiny jsou jiné:

PříznakPravděpodobná příčina
Vidíš a stahuješ, ale nic nenahraješTvůj účet subuživatele nemá oprávnění vytvářet nebo aktualizovat soubory
Nové soubory vytvoříš, existující nepřepíšešVytváření povoleno, aktualizace ne
Nejde mazat ani přejmenovatChybí oprávnění mazat
Jeden konkrétní soubor je vždy odmítnutEgg serveru ho uvádí v denylistu souborů
Nahrávání selhává nebo se ořezává, přestože dřív fungovaloDosažen limit disku
Odmítnuto je samotné přihlášeníChybí oprávnění SFTP nebo špatný formát uživatelského jména

Původní Pterodactyl dělí přístup k souborům na samostatná oprávnění - čtení, čtení obsahu, vytváření, aktualizace, mazání, archivace a samotné SFTP - a SFTP služba kontroluje stejná oprávnění jako správce souborů v prohlížeči. Subuživatel s právem čtení a SFTP, ale bez aktualizace, zažije přesně situaci „připojen, ale nejde upravovat“. Majitel serveru ji opraví úpravou oprávnění dotyčného člověka, ne změnou čehokoli v souborech. Subuživatelé a nejmenší oprávnění popisuje, co komu přidělit.

Denylist souborů v eggu je druhá příčina specifická pro panely. Autor eggu může označit soubory, kterých se uživatelé serveru nesmí dotknout (často licenční soubor nebo startovací skript spravovaný hostingem), a SFTP služba je odmítne s chybou oprávnění i majiteli serveru. Pokud je pořád odmítnutý přesně jeden soubor, zatímco sousední jsou v pořádku, podezřívej nejdřív tohle. Pterodactyl eggy pro herní servery vysvětluje, co všechno egg řídí.

Na RE:NODE je SFTP dostupné na každém serveru s přihlašovacími údaji vydanými pro každý server zvlášť, ne pro každý účet, a údaje k připojení najdeš u serveru v panelu. Přístup pro další lidi se řídí rolemi, týmy a oprávněními s podrobným nastavením práv k souborům, takže „jen soubory, bez mazání“ je skutečné nastavení. Když údaj o disku serveru dosáhne limitu, zápisy se zastaví; grafy v konzoli ukazují disk proti limitu, což je nejrychlejší způsob, jak tuto příčinu potvrdit nebo vyloučit. Průvodce soubory ukazuje správce souborů a SFTP vedle sebe a SFTP a správce souborů popisuje klienty, skriptované přenosy a soubory, které běžící server drží otevřené.

Kontrolní seznam, který příčinu najde za pět minut#

Procházej seznam shora a zastav se u první věci, která je špatně:

  1. Je to chyba přihlášení? Permission denied (publickey,password) znamená autentizaci, ne soubory.
  2. Týká se to všech souborů, nebo jednoho? Když je odmítnuto všechno, ukazuje to na tvůj účet, připojení nebo disk. Jeden soubor ukazuje na jeho vlastníka, práva, příznak neměnnosti nebo denylist panelu.
  3. Kdo jsi a komu to patří? id, pak ls -la na soubor a jeho složku. Porovnej vlastníka, skupinu a bity, které se na tebe vztahují.
  4. Je složka zapisovatelná? Nové soubory, mazání, přejmenování i ukládání přes dočasný soubor potřebují w na složce.
  5. Je disk plný nebo jen pro čtení? df -h, df -i, findmnt. Na panelu graf disku.
  6. Je soubor neměnný? lsattr.
  7. Chová se jiný klient jinak? Pokud ano, podívej se na nahrávání přes dočasné soubory a nastavení atributů v tom, který selhává.
  8. Na panelu: co smí tvůj účet? Požádej majitele, aby zkontroloval tvá oprávnění k souborům.

Každý krok je jeden příkaz nebo jedna obrazovka a na pořadí záleží: postupuje od levných a častých příčin k vzácným.

FAQ#

Proč můžu přes SFTP stahovat, ale ne nahrávat?

Ke stahování je potřeba právo čtení na souboru; k nahrávání právo zápisu na cílové složce. Výchozí práva (644 pro soubory, 755 pro složky) dávají čtení všem a zápis jen vlastníkovi. Pokud se přihlásíš jako jiný uživatel, než který složku vlastní, dostaneš přesně tohle. Přihlas se jako vlastník nebo s ním sdílej skupinu.

Opraví SFTP permission denied příkaz chmod 777?

Často jen skryje příznak a vždy vyrobí větší problém. Každý uživatel a proces na stroji pak může ty soubory přepsat a nové soubory vytvořené službou stejně dorazí s běžnými právy, takže se problém vrátí. Správné řešení je sdílená skupina se složkami se setgidem a umask 002.

Proč WinSCP hlásí, že nahrání uspělo, ale nastavení práv selhalo?

Soubor můžeš zapsat, ale nemůžeš měnit jeho atributy, obvykle proto, že nejsi jeho vlastník. Obsah byl nahrán. Zapni „Ignore permission errors“ v nastavení přenosu nebo pro danou lokalitu zakaž WinSCP nastavovat při nahrávání práva a časová razítka.

Po přihlášení k chrootovanému účtu nemůžu nahrávat do kořenové složky. Je to rozbité?

Ne. OpenSSH vyžaduje, aby chrootová složka patřila uživateli root a nebyla zapisovatelná pro uživatele, takže nejvyšší úroveň je záměrně jen pro čtení. Tvůj administrátor by měl uvnitř vězení vytvořit podsložku patřící tvému uživateli a ty nahráváš tam.

Proč můžu na herním panelu upravovat některé soubory, ale jiné ne?

Buď má tvůj účet subuživatele jen některá oprávnění k souborům (například vytváření bez aktualizace), nebo je soubor v denylistu eggu. Vlastnictví není důvod na panelu postaveném na Pterodactylu, protože každý soubor ve složce serveru patří stejnému uživateli kontejneru.

Může plný disk způsobit permission denied?

Doslova ne, ale mnoho SFTP klientů hlásí neúspěšný zápis nejasně a na ext4 kvůli blokům vyhrazeným pro root téměř plný disk odmítne běžné uživatele dřív než root. Než začneš měnit jakákoli práva, zkontroluj df -h a df -i.