ഹുക്ക് root ആയി കൈകൊണ്ട് പ്രവർത്തിപ്പിക്കുമ്പോൾ ഇത് പ്രവർത്തിക്കുന്നു, തിരികെ നൽകുന്നത് Operation not permitted സേവനം അത് ആരംഭിക്കുന്ന നിമിഷത്തിൽ. ആ രണ്ട് പ്രവർത്തനങ്ങൾക്കിടയിൽ ഫയൽ മാറിയില്ല; പരിസ്ഥിതി മാറി. systemd പ്രക്രിയയ്ക്ക് ചെറിയ ലോകം നൽകുന്നു: കുറച്ച് കഴിവുകൾ, മറ്റൊരു /dev, വായന-മാത്ര ഫയൽസിസ്റ്റം പാതകൾ, ജോലികൾക്കുള്ള പരിധി. പരാജയത്തെ ഒരു നിർദ്ദിഷ്ട പ്രവർത്തനം നിരസിച്ച അതിർത്തിയായി വായിക്കുക, തകർന്ന സ്ക്രിപ്റ്റായല്ല.

നിരസിക്കപ്പെട്ട പ്രവർത്തനത്തിൽ നിന്ന് തുടങ്ങുക

unit പരാജയപ്പെട്ടു എന്ന് പറയുന്ന ലോഗ് വരി നിങ്ങൾക്ക് കാര്യമായി ഒന്നും പറയുന്നില്ല. ഉപയോഗപ്രദമായ വരി നിരസിക്കപ്പെട്ട കോളിന്റെ പേര് പറയുന്നു: തുറക്കാനാകാത്ത ഉപകരണ നോഡ്, എഴുതാനാകാത്ത ഡയറക്ടറി, സൃഷ്ടിക്കാനാകാത്ത namespace. ഒരു ഡയറക്ടീവ് പോലും തൊടുന്നതിന് മുൻപ് ആ കോൾ കണ്ടെത്തുക, കാരണം ഓരോന്നും വ്യത്യസ്ത നിയന്ത്രണവുമായി ചേരുന്നു. അതിനുശേഷം പാക്കേജ് അയച്ച ഫയലിനുപകരം യഥാർത്ഥത്തിൽ പ്രവർത്തിച്ച unit വായിക്കുക, drop-in ഉൾപ്പെടെ.

താഴെയുള്ള ക്വറി ഫ്രാഗ്മെന്റ് പാത, drop-in ഡയറക്ടറികൾ, ഉപകരണമോ ഫയൽസിസ്റ്റമോ നിരസിക്കുമ്പോൾ പ്രധാനമായ ഗുണങ്ങൾ എന്നിവ അച്ചടിക്കുന്നു. ഏത് അതിർത്തി പ്രസക്തമെന്ന് തീരുമാനിക്കുന്നതിന് മുൻപ് എല്ലാം വായിക്കുക:

systemctl show "[email protected]" -p FragmentPath -p DropInPaths -p PrivateDevices -p DevicePolicy -p DeviceAllow -p ProtectHome -p ProtectSystem -p TasksMax
journalctl -u "[email protected]" -b --no-pager | grep -iE 'operation not permitted|permission denied|cannot open|failed'

ആ ബ്ലോക്കിൽ ഒന്നും എഴുതുന്നില്ല. നിരസിക്കപ്പെട്ട കോൾ ജേണലിൽ ഇല്ലെങ്കിൽ, ഡയറക്ടീവുകൾ ഊഹിക്കുന്നതിനുപകരം ഒരു പ്രവർത്തനത്തിന് ക്ലയന്റിന്റെ വിശദാംശം കൂട്ടുക. പ്രവർത്തിക്കുന്ന പ്രക്രിയ unit ആരംഭിച്ചു എന്ന് തെളിയിക്കുന്നു, ഹുക്ക് ആവശ്യമായ അധികാരങ്ങളോടെ പ്രവർത്തിച്ചു എന്നല്ല.

namespace-ന് TUN ഉപകരണം ഒരിക്കലും ഉപയോഗിക്കാത്ത mount അവകാശങ്ങൾ വേണം

ഒരു ഹുക്കിനുള്ളിൽ ഒരുപോലെ തോന്നുന്ന രണ്ട് പ്രവർത്തനങ്ങൾക്ക് വ്യത്യസ്ത അനുമതി പ്രൊഫൈലുകളുണ്ട്. /dev/net/tun തുറക്കാനും ഇന്റർഫേസ് സൃഷ്ടിക്കാനും നെറ്റ്‌വർക്ക് അഡ്മിനിസ്ട്രേഷനും ആ നോഡിലേക്കുള്ള പ്രവേശനവും വേണം. പേരുള്ള നെറ്റ്‌വർക്ക് namespace സൃഷ്ടിക്കാനും mount ജോലി വേണം, കാരണം namespace ഉപകരണം പുതിയ /sys കാഴ്ച mount ചെയ്ത് ഒരു സ്റ്റേറ്റ് ഡയറക്ടറി അതിന്റെ സ്ഥാനത്ത് ബന്ധിക്കുന്നു. അപ്സ്ട്രീം ക്ലയന്റ് unit mount അഡ്മിനിസ്ട്രേഷൻ ബോധപൂർവം തന്റെ അതിർത്തി കൂട്ടത്തിന് പുറത്ത് വയ്ക്കുന്നു, അതിനാൽ namespace ഘട്ടം നിരസിക്കപ്പെടുന്നു, ടണൽ തന്നെ പ്രവർത്തിക്കുമായിരുന്നു.

അതുകൊണ്ടാണ് ഉപകരണ നോഡ് നൽകുന്നത് സ്ക്രിപ്റ്റിനെ രക്ഷിക്കാത്തത്. ഉപകരണ അനുമതി ഒരു ചോദ്യത്തിന് ഉത്തരം നൽകുന്നു, ഈ പ്രക്രിയയ്ക്ക് ഈ നോഡ് തുറക്കാമോ, namespace-ന്റെ ചോദ്യം മറ്റൊന്നാണ്. എന്തെങ്കിലും വിപുലീകരിക്കുന്നതിന് മുൻപ് പരാജയപ്പെടുന്ന കോളിനെ അതിന്റെ കഴിവുമായി ചേർക്കുക.

നിങ്ങളുടെ shell-ലെ പരിശോധന പരിധിയില്ലാത്ത root-നുള്ള എല്ലാ കഴിവുകളും പാരമ്പര്യമായി നേടുന്നു, unit തന്റെ അതിർത്തി കൂട്ടം നിലനിർത്തിയത് നേടുന്നു. ആ രണ്ട് പ്രവർത്തനങ്ങൾ വ്യത്യസ്ത പരീക്ഷണങ്ങളാണ് ബൈനറി ഒന്നുതന്നെയാണെങ്കിലും.

ഉപകരണങ്ങൾ, സംരക്ഷിത പാതകൾ, ജോലി പരിധികൾ

നിരസിക്കപ്പെട്ട പ്രവർത്തനം അറിഞ്ഞുകഴിഞ്ഞാൽ, മൂന്ന് ഡയറക്ടീവ് കൂട്ടങ്ങൾ മിക്ക പരാജയങ്ങളും വിശദീകരിക്കുന്നു. ഉപകരണ പ്രവേശനം നിയന്ത്രിക്കുന്നത് PrivateDevices, അത് /dev നിഷ്കർഷിച്ച കുറഞ്ഞ സ്യൂഡോ-ഉപകരണ കൂട്ടം കൊണ്ട് മാറ്റുന്നു, കൂടാതെ DevicePolicy ഒപ്പം DeviceAllow, അവ cgroup എന്ത് അനുവദിക്കുന്നു എന്ന് തീരുമാനിക്കുന്നു. /dev/net/tun ആ കുറഞ്ഞ കൂട്ടത്തിന്റെ ഭാഗമല്ല, അതിനാൽ PrivateDevices=yes ഉള്ള unit ഉപകരണ നയം എന്ത് പറഞ്ഞാലും അത് തുറക്കാനാവില്ല.

ഫയൽസിസ്റ്റം സംരക്ഷണം രണ്ടാമത്തെ ചോദ്യത്തിന് ഉത്തരം നൽകുന്നു. ProtectHome=yes ആക്കുന്നു /home, /root എന്നിവയെ /run/user അപ്രാപ്യമാക്കുന്നു, കൂടാതെ ProtectSystem=full ആക്കുന്നു /usr, /boot എന്നിവയെ /etc വായന-മാത്രമാക്കുന്നു. അതിനാൽ സ്വന്തം കോൺഫിഗറേഷൻ ഫയലിന് അരികിൽ എഴുതുന്ന ഹുക്ക് നിങ്ങളുടെ shell-ൽ പ്രവർത്തിക്കുന്നു, unit-ന് കീഴിൽ പരാജയപ്പെടുന്നു, കാണാത്ത കഴിവിന്റെ അതേ അനുമതി രൂപത്തോടെ. എഴുതാവുന്ന ഇൻപുട്ട് നയം അനുവദിക്കുന്ന പാതയിലേക്ക് മാറ്റുക, അല്ലെങ്കിൽ ഇടുങ്ങിയ ReadWritePaths= എൻട്രി ചേർക്കുക.

വിഭവ പരിധികൾ മൂന്നാമത്തെ കൂട്ടമാണ്, ഏറ്റവും വ്യക്തമല്ലാത്തതും. TasksMax= unit എത്ര ജോലികൾ സൃഷ്ടിക്കാമെന്ന് പരിമിതപ്പെടുത്തുന്നു, ഫയൽ ഡിസ്ക്രിപ്റ്റർ പരിധി socket-കൾക്കും ഹാൻഡിലുകൾക്കും അതേപോലെ പ്രവർത്തിക്കുന്നു. പരിധി കവിഞ്ഞ് വളർന്ന വിന്യാസം അനുമതി പിശകിനുപകരം വിഭവ പിശകോടെ പരാജയപ്പെടുന്നു, അതുകൊണ്ടാണ് കൃത്യമായ സന്ദേശം ഇപ്പോഴും പ്രധാനമായിരിക്കുന്നത്.

namespace ഘട്ടം ഹുക്കിൽ നിന്ന് പുറത്തെടുക്കുക

ക്ലയന്റ് ഉണ്ടാകരുതാത്ത ഒരു അധികാരം ആവശ്യമുള്ള തയ്യാറെടുപ്പ് അതിന്റെ സ്വന്തം unit-ൽ വരുന്നു. ക്ലയന്റിന് മുൻപ് പ്രവർത്തിക്കുന്ന, ഫലം സൂക്ഷിക്കുന്ന, ബന്ധത്തിന് മുൻപ് ക്രമീകരിച്ച oneshot namespace ഘട്ടത്തിന് വേണ്ടത് നൽകുന്നു, ആ അവകാശങ്ങൾ ടണൽ പ്രക്രിയയ്ക്ക് നൽകാതെ. പിന്നീട് ക്ലയന്റ് സ്വന്തം up ഹുക്കിൽ നിന്ന് സ്ക്രിപ്റ്റ് വിളിക്കുന്നതിനുപകരം ആ unit-നെ സൂചിപ്പിക്കുന്നു.

താഴെയുള്ള ടെംപ്ലേറ്റ് ഒരു തുടക്ക രൂപമാണ്, വായിക്കാതെ പ്രയോഗിക്കേണ്ട ഒന്നല്ല. തയ്യാറെടുപ്പ് അധികാരം കഴിയുന്നിടത്ത് തന്നെ നിർത്തി ടണൽ unit-നെ തൊടാതെ വിടുന്നു:

# /etc/systemd/system/[email protected]
[Unit]
Description=Namespace preparation for %i
Before=openvpn-client@%i.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/local/sbin/netns-up.sh %i
CapabilityBoundingSet=CAP_NET_ADMIN CAP_SYS_ADMIN
[Install]
WantedBy=multi-user.target

പാക്കേജ് ചെയ്ത unit തിരുത്തുന്നതിനുപകരം drop-in ഉപയോഗിച്ച് ക്രമം ചേർക്കുക, അപ്‌ഗ്രേഡിന് നിങ്ങളുടെ മാറ്റം നിശബ്ദമായി വീഴ്ത്താനാവാതിരിക്കാൻ. ഡയറക്ടറി ഇൻസ്റ്റൻസ് പേരുമായി ബന്ധിപ്പിച്ചിരിക്കുന്നു, അതിനാൽ രണ്ടാമത്തെ പ്രൊഫൈലിന് സ്വന്തം ഫയൽ വേണം:

sudo mkdir -p /etc/systemd/system/[email protected]
sudo tee /etc/systemd/system/[email protected]/10-namespace.conf >/dev/null <<'CONF'
[Unit]
[email protected]
[email protected]
CONF
sudo systemctl daemon-reload

മാറ്റത്തിന് ശേഷം അതേ കോൾ ആവർത്തിക്കുക

അതേ കോൾ വ്യത്യസ്ത ഫലം നൽകുമ്പോൾ മാത്രമേ അറ്റകുറ്റപ്പണി സ്ഥിരീകരിക്കൂ. രണ്ട് unit-കളും വീണ്ടും ആരംഭിക്കുക, പരാജയപ്പെട്ട പ്രവർത്തനം നടത്തുക, അതിന്റെ ഫലം മാറ്റത്തിന് മുൻപ് സൂക്ഷിച്ച ജേണൽ വരിയുമായി താരതമ്യം ചെയ്യുക. ഹുക്ക് ഇനി ഒരിക്കലും പ്രവർത്തിക്കാതിരിക്കെ ആരംഭിക്കുന്ന unit അറ്റകുറ്റപ്പണിയല്ല.

താഴെയുള്ള ക്രമം താരതമ്യം സത്യസന്ധമായി നിർത്തുന്നു, കാരണം അത് unit-ന്റെ നിറമല്ല, നിരസിക്കപ്പെട്ട കോൾ പരിശോധിക്കുന്നു. അതിന്റെ ഔട്ട്പുട്ട് മാറ്റത്തിന് മുൻപ് പിടിച്ച ജേണൽ വരിയുടെ അടുത്ത് സൂക്ഷിക്കുക:

sudo systemctl restart "[email protected]" "[email protected]"
systemctl status "[email protected]" --no-pager
journalctl -u "[email protected]" -b --no-pager | grep -c 'Operation not permitted'
ip -brief addr show tun0

അവസാന വരി വായിക്കുന്നതിനുപകരം നിരസിക്കലുകൾ എണ്ണുക, കാരണം ഒരു ഹുക്ക് പരാജയപ്പെടാം, വീണ്ടും ശ്രമിക്കാം, വിജയിക്കാം, അതിർത്തി നീങ്ങിയോ എന്ന് എണ്ണം മാത്രം കാണിക്കുന്നു. drop-in-ൽ നിങ്ങൾ അയച്ചുവിട്ട ഡയറക്ടീവും കാരണവും പറയുന്ന ഒരു കുറിപ്പ് വിടുക, കാരണം അടുത്ത അപ്‌ഗ്രേഡ് നിങ്ങളുടെ കോൺഫിഗറേഷനെ പാക്കേജിന്റെ സ്ഥിരസ്ഥിതിയുമായി താരതമ്യം ചെയ്യുന്നു. എല്ലാ സംരക്ഷണവും ഓഫാക്കിയ ശേഷം മാത്രം ആരംഭിക്കുന്ന unit ശരിയാക്കപ്പെട്ടിട്ടില്ല.

അനുബന്ധ ലേഖനങ്ങൾ