Hur man använder kommandot chroot på Linux

By rik

Chroot-kommandot kan fungera som en säkerhetsåtgärd, skapa isolerade utvecklings- eller testmiljöer och generellt förbättra systemsäkerheten. Vi ska visa dig det mest lättförståeliga sättet att använda det.

Vad innebär chroot?

När man bedömer ett kommandos användbarhet måste man överväga både dess funktionalitet och hur enkelt det är att använda. Om ett kommando är för krångligt eller tidsödande att använda minskar dess praktiska värde avsevärt. Om ingen använder det, spelar det ingen roll hur bra det är i teorin.

I diskussioner med Linux-användare, både ansikte mot ansikte och på nätforum, verkar chroot-kommandot ha ett rykte om sig att vara svårt och krångligt att konfigurera. Detta leder till att många inte drar nytta av detta kraftfulla verktyg.

Med chroot kan du skapa och köra program eller interaktiva skal som Bash i ett avgränsat filsystem som inte har tillgång till det vanliga filsystemet. Allt inom chroot-miljön är strikt begränsat till den. Ingenting i chroot-miljön kan se förbi sin egen, specifika rotkatalog utan att utöka behörigheterna till root. Det är därför den här typen av miljö kallas för ett chroot-fängelse. Termen ”fängelse” ska dock inte förväxlas med FreeBSD:s jail-kommando, som skapar en chroot-miljö som är säkrare än den vanliga chroot-miljön.

Lyckligtvis finns det ett enkelt sätt att använda chroot, vilket vi nu ska gå igenom. Vi kommer att använda vanliga Linux-kommandon som fungerar på alla distributioner. Vissa Linux-distributioner har dedikerade verktyg för att skapa chroot-miljöer, som till exempel debootstrap för Ubuntu, men vi håller oss här till en mer distributionsagnostisk metod.

När är chroot användbart?

En chroot-miljö erbjuder funktionalitet som liknar en virtuell maskin, men med mindre resurskrav. Det ”fångade” systemet behöver inte en hypervisor, såsom VirtualBox eller Virtual Machine Manager. Det behöver inte heller en egen kärna; det delar istället den befintliga kärnan med systemet.

I vissa avseenden liknar chroot-miljöer mer behållare som LXC än virtuella maskiner. De är lätta, snabba att implementera och kan automatiseras. Precis som behållare kan de konfigureras för att installera precis så mycket av operativsystemet som behövs för de specifika uppgifterna. Frågan om vad som behövs beror helt på hur du tänker använda chroot-miljön.

Vanliga användningsområden inkluderar:

  • **Programvaruutveckling och testning:** Utvecklare skriver mjukvara, och ett separat team (PV) testar den. Ibland upptäcker PV problem som inte kan återskapas på utvecklarens dator, eftersom utvecklaren kan ha specifika verktyg och bibliotek installerade som inte finns på testmiljön. Chroot gör att utvecklare kan testa mjukvaran i en ”ren” miljö innan den levereras till PV. Denna miljö kan konfigureras med de minimala beroenden som krävs för att mjukvaran ska fungera.
  • **Reducerad utvecklingsrisk:** Utvecklare kan skapa en isolerad utvecklingsmiljö, vilket förhindrar att experimentell kod skadar den ordinarie datorn.
  • **Körning av äldre programvara:** Ibland behöver man köra en äldre version av ett program. Om denna version har krav som krockar med den befintliga Linux-installationen, kan en chroot-miljö användas för att isolera den gamla programvaran.
  • **Systemåterställning och filsystemuppgraderingar:** Om en Linux-installation inte fungerar korrekt kan du använda chroot för att montera det skadade filsystemet på en Live CD. Detta gör att du kan arbeta med det skadade systemet som om det var monterat vid roten (/). Filsökvägarna i det skadade systemet kommer att fungera som förväntat. En liknande teknik användes i en artikel om att migrera Linux-filsystem från ext2/ext3 till ext4.
  • **Säkerhetsisolering:** Att köra en FTP-server eller andra internetanslutna tjänster i en chroot-miljö minskar skadan som en extern angripare kan orsaka, vilket är ett effektivt sätt att stärka systemets säkerhet.

Skapa en chroot-miljö

Vi börjar med att skapa en katalog som ska fungera som rotkatalog för chroot-miljön. För att enkelt referera till den katalogen, skapar vi en variabel som lagrar katalogens sökväg. I det här fallet, sätter vi variabeln för att peka på en katalog som heter ”testroot”. Det spelar ingen roll om katalogen inte existerar ännu, eftersom vi kommer att skapa den snart. Om katalogen redan finns, ska den vara tom.

chr=/home/dave/testroot

Om katalogen inte finns, måste vi skapa den. Detta gör vi med följande kommando, där alternativet -p (föräldrar) ser till att alla nödvändiga överordnade kataloger skapas samtidigt:

mkdir -p $chr

Vi behöver skapa kataloger för att lagra de delar av operativsystemet som vår chroot-miljö kräver. Vi kommer att bygga en minimal Linux-miljö som använder Bash som interaktivt skal, samt kommandona touch, rm och ls. Det gör att vi kan använda alla Basha inbyggda kommandon, samt skapa, lista och ta bort filer. I detta enkla exempel är det allt vi behöver.

Vi listar katalogerna som ska skapas inom {} med brace expansion.

mkdir -p $chr/{bin,lib,lib64}

Nu byter vi katalog till vår nya rotkatalog.

cd $chr

Låt oss kopiera de binärfiler som vi behöver för vår minimalistiska Linux-miljö från den vanliga ”/bin”-katalogen till vår chroot-katalog ”/bin”. Alternativet -v (verbose) får cp att meddela vad den gör när varje kopiering utförs.

cp -v /bin/{bash,touch,ls,rm} $chr

Filerna kopieras:

Dessa binärfiler har beroenden. Vi behöver hitta dem och kopiera dessa filer till vår miljö också, annars kommer bash, touch, rm och ls inte att fungera. Vi gör detta i tur och ordning för vart och ett av våra valda kommandon. Vi börjar med Bash. Kommandot ldd listar beroenden för oss.

ldd /bin/bash

Beroenden identifieras och visas i terminalfönstret:

Vi måste kopiera dessa filer till vår nya miljö. Att manuellt plocka ut detaljerna från listan och kopiera filerna en i taget är tidskrävande och riskabelt.

Lyckligtvis kan vi göra det halvautomatiskt. Vi listar beroenden igen, och skapar en lista. Sedan går vi igenom listan och kopierar filerna.

Vi använder ldd för att lista beroenden och matar resultaten via ett rör till egrep. Att använda egrep är som att använda grep med alternativet -E (extended regular expressions). Alternativet -o (only matching) begränsar utdata till de matchande delarna av raderna. Vi letar efter matchande biblioteksfiler som slutar med en siffra [0-9].

list="$(ldd /bin/bash | egrep -o '/lib.*.[0-9]')"

Vi kan kontrollera innehållet i listan med echo:

echo $list

Nu när vi har listan kan vi gå igenom den med följande loop och kopiera filerna en i taget. Vi använder variabeln i för att gå igenom listan. För varje element i listan, kopierar vi filen till vår chroot-rotkatalog, som är lagrad i variabeln $chr.

Alternativet -v (verbose) får cp att rapportera varje kopia som den utför. Alternativet –parents ser till att alla saknade överordnade kataloger skapas i chroot-miljön.

for i in $list; do cp -v --parents "$i" "${chr}"; done

Och det här är utdata:

Vi kommer att använda den här tekniken för att hitta beroenden för vart och ett av de andra kommandona. Och vi kommer att använda loopen för att utföra kopieringen. Den goda nyheten är att vi bara behöver göra en liten ändring i kommandot som samlar in beroenden.

Vi kan hämta kommandot från kommandohistoriken genom att trycka på uppåtpilen några gånger och sedan redigera det. Kopieringsloopen behöver inte ändras.

Här har vi använt uppåtpilen för att hitta kommandot, och redigerat det till touch istället för bash.

list="$(ldd /bin/touch | egrep -o '/lib.*.[0-9]')"

Nu kan vi upprepa exakt samma loop-kommando som tidigare:

for i in $list; do cp -v --parents "$i" "${chr}"; done

Och våra filer kopieras:

Vi kan nu redigera listkommandot för ls:

list="$(ldd /bin/ls | egrep -o '/lib.*.[0-9]')"

Återigen, använder vi samma loop. Den bryr sig inte om vilka filer som finns i listan, utan går blint igenom listan och kopierar filerna.

for i in $list; do cp -v --parents "$i" "${chr}"; done

Och beroenden för ls kopieras:

Vi redigerar listkommandot en sista gång för att fungera för rm:

list="$(ldd /bin/ls | egrep -o '/lib.*.[0-9]')"

Vi använder loopkommandot en sista gång:

for i in $list; do cp -v --parents "$i" "${chr}"; done

De sista av våra beroenden kopieras till vår chroot-miljö. Vi är äntligen redo att använda chroot-kommandot. Detta kommando sätter roten för chroot-miljön och anger vilket program som ska köras som skal.

sudo chroot $chr /bin/bash

Vår chroot-miljö är nu aktiv. Terminalfönstrets prompt har ändrats, och det interaktiva skalet är det som hanteras av bash-skalet i vår miljö.

Vi kan prova de kommandon vi har tagit in i miljön.

ls
ls /home/dave/Documents

Kommandot ls fungerar som förväntat när vi använder det i miljön. När vi försöker nå en katalog utanför miljön, misslyckas kommandot.

Vi kan använda touch för att skapa en fil, ls för att lista den och rm för att ta bort den.

touch sample_file.txt
ls
rm sample_file.txt
ls

Självklart kan vi även använda de inbyggda kommandona som Bash-skalet tillhandahåller. Om du skriver hjälp på kommandoraden, listar Bash dem.

help

Använd exit för att lämna chroot-miljön:

exit

Om du vill ta bort chroot-miljön, tar du helt enkelt bort den:

rm -r testroot/

Detta raderar rekursivt alla filer och kataloger i chroot-miljön.

Automatisera för enkelhet

Om du tror att chroot-miljöer kan vara användbara, men de verkar jobbiga att sätta upp, kom ihåg att du alltid kan minska stressen och risken som uppstår med repetitiva uppgifter med hjälp av alias, funktioner och skript.