Покрените радњу након VPN везе као корисник, а не као демон
Променљива окружења која каже USER=alice не мења под којим налогом hook ради. Раздвојите догађај, окидач и радњу, а затим докажите UID.
Hook-ови везе на VPN демону раде као демон, а то обично значи да раде као root. У тренутку када један од тих hook-ова упише у нечији почетни директоријум или поново покрене помоћника радне површине, дали сте мрежном догађају могућност да делује као било који локални корисник. Уобичајени пречица, прочитати корисничко име из променљиве окружења и проследити га, то не исправља. Она само преименује радњу без промене налога који је извршава. Оно што функционише је троделна предаја у којој привилеговани корак каже шта се догодило, а засебна јединица извршава радњу под исправним идентитетом.
Корисничко име у окружењу није прекидач идентитета
Unix одлучује чега процес сме да се дотакне према свом ефективном корисничком ID-у, а не према низовима у свом окружењу. Постављање USER=alice или извоз LOGNAME мења шта немаран софтвер исписује у свом излазу; не мења ништа у проверама власништва датотека. Hook који ради као root са том променљивом и даље отвара Алисине датотеке као root.
Ни имена нису исто име. Пријава за даљински приступ, локални Unix налог и уобичајено име сертификата три су идентификатора која се често поклапају, а понекад не. Корисник који се аутентификује као a.smith можда нема никакав локални налог или се пресликава на asmith преко услуге именика. Сваки дизајн који претпоставља да један низ служи све три улоге сломиће се већ на првом извођачу.
Дакле прво питање није „који је корисник повезан“ него „ком локалном налогу је дозвољено да изведе ову радњу“. Одговорите на то из сопствене базе података о налозима, а не из онога што је клијент послао:
id -u alice
getent passwd alice | cut -d: -f1,3,6
stat -c '%U:%G %a %n' /home/alice/.local/state/vpn-status.json
Трећа наредба је она коју људи прескачу. Ако је циљна датотека у власништву root-а јер ју је створио претходни hook, исправно конфигурисана корисничка радња неће успети са грешком дозволе која изгледа као проблем systemd-а и није.
Демон остаје тамо где јесте
Промена сопственог User= VPN услуге на Алису је погрешна полуга. Мења како демон повезује интерфејсе, чита кључеве, уписује своју датотеку стања и управља рутама, и премешта сав тај ризик у јединицу која је радила. Демону су потребне његове привилегије; наредној радњи нису.
Погледајте шта јединица заиста ради пре него што је дотакнете. Две наредбе вам кажу идентитет извршавања и тачне командне линије на снази, укључујући све што је додало премошћење:
systemctl show -p User -p Group -p ExecStart openvpn-server@server
systemctl cat openvpn-server@server
При подразумеваној инсталацији пакета демон је root, а скрипта --up то наслеђује. Потврдите то уместо да претпостављате, јер је очврснута дистрибуција можда преместила на наменски налог, а ручно написани drop-in може покретати hook кроз омотач са другачијим правилима.
Три именована дела, један узак окидач
Распоред који преживљава одржавање има догађај, окидач и радњу. Демон извештава да се именована сесија подигла. Окидач прихвата ту малу чињеницу и тражи једну фиксну радњу. Радња ради под локалним налогом који поседује датотеке које дотиче. Ништа у ланцу не прихвата произвољну путању наредбе.
Сама радња је обична сервисна јединица, а идентитет је једна директива унутар ње:
[Service]
Type=oneshot
User=alice
Group=alice
ExecStart=/usr/local/bin/refresh-vpn-status --slot %i
Обратите пажњу да User=alice важи за целу јединицу, а systemd документује један изузетак који вреди знати: наредба са префиксом + ради са пуним привилегијама без обзира на то. Тај префикс је легитиман алат за један привилеговани корак и прикладан начин да поништите раздвајање које сте управо изградили, зато сваки + у тој јединици третирајте као нешто што треба оправдати у прегледу.
Држите улаз окидача минималним и не-тајним. Идентификатор сесије, пресликани налог и временска ознака обично су све што је потребно. Никада не предајте преко границе фрагмент љуске, путању извршне датотеке ни блок окружења који је доставио клијент, јер страна која прима нема начина да разликује легитимну вредност од убачене.
Проверите идентитет који је заиста радио
Преглед конфигурације није доказ. Након одобрене тестне везе потврдите UID који је дотакао датотеку и UID који демон још користи:
stat -c '%U %G %y %n' /home/alice/.local/state/vpn-status.json
ps -o user=,pid=,cmd= -p "$(pgrep -o -f 'openvpn --daemon')"
systemd-run --uid=alice --pipe /usr/local/bin/refresh-vpn-status --dry-run
Први ред би требало да покаже Алису и временску ознаку унутар вашег тестног прозора. Други би требало да и даље показује root или сервисни налог пакета, што доказује да се демон није померио. Трећи је најјефтинији начин да тестирате дозволе радње без чекања на стварно поновно повезивање.
Ако је власник датотеке Алиса, али су се њена група или режим променили између покретања, тражите UMask= или разлику у дозволама директоријума уместо логичке грешке. Ако се временска ознака уопште није померила, окидач никада није активиран, а користан следећи корак је journalctl -u за јединицу радње уместо још једног поновног повезивања клијента.
Шта догађај везе још увек не доказује
Успостављен тунел је једна чињеница. То не значи да је сесија радне површине откључана, да је магистрала сесије доступна или да је приватни ресурс који радња жели већ доступан. oneshot јединица под Алисиним UID-ом има њен идентитет и ништа од њене сесије, зато све што захтева графичку магистралу мора да прође кроз подржани механизам корисничке сесије и да одреди шта се дешава када је она одјављена.
Поновна повезивања се такође понављају. Преносни рачунар који спава у возу може да произведе десетак догађаја везе у једном сату, а hook који сваки пут дода ред претвара датотеку стања у дневник који нико не може да чита. Учините радњу идемпотентном или јој дозволите да замени један запис са кључем по сесији.
На крају, ограничите радијус штете у самој јединици: приказ датотечног система само за читање изван директоријума стања, без нових привилегија и са изричитим временским ограничењем. Раздвајање демона и корисничке радње вредно је само по себи, али вреди много више када радња не може да учини ништа осим оне једне ствари коју сте одобрили.