మీ OpenVPN hook-ను ఏ systemd sandbox తిరస్కరించిందో కనుగొనడం ఎలా
Hook rootగా పనిచేస్తుంది మరియు systemd క్రింద విఫలమవుతుంది, ఎందుకంటే unit తక్కువ సామర్థ్యాలు, చిన్న /dev మరియు చదవడానికి-మాత్రమే మార్గాలను ఉంచుకుంటుంది.
మీరు దాన్ని rootగా చేతితో అమలు చేసినప్పుడు hook పనిచేస్తుంది మరియు తిరిగి ఇస్తుంది 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 ప్రారంభమైందని నిరూపిస్తుంది, hookకు అవసరమైన అధికారాలతో నడిచిందని కాదు.
TUN పరికరం ఎప్పుడూ ఉపయోగించని mount హక్కులు namespaceకు అవసరం
ఒక hook లోపల ఒకేలా కనిపించే రెండు ఆపరేషన్లకు వేరే అనుమతి ప్రొఫైల్స్ ఉంటాయి. తెరవడం /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 చదవడానికి-మాత్రమేగా మారుతాయి. కాబట్టి తన సొంత కాన్ఫిగరేషన్ ఫైల్ పక్కన రాసే hook మీ shellలో పనిచేసి unit క్రింద విఫలమవుతుంది, లేని సామర్థ్యం వలె అదే అనుమతి ఆకృతితో. రాయగలిగే ఇన్పుట్ను విధానం అనుమతించే మార్గానికి తరలించండి, లేదా ఒక సన్నని ReadWritePaths= ఎంట్రీని జోడించండి.
వనరు పరిమితులు మూడవ సమూహం, మరియు అతి తక్కువ స్పష్టమైనవి. TasksMax= unit సృష్టించగల పనుల సంఖ్యను పరిమితం చేస్తుంది, మరియు ఫైల్-డిస్క్రిప్టర్ పరిమితి సాకెట్లు మరియు హ్యాండిల్స్కు అదే విధంగా ప్రవర్తిస్తుంది. పరిమితిని దాటి పెరిగిన డిప్లాయ్మెంట్ అనుమతి లోపం బదులు వనరు లోపంతో విఫలమవుతుంది, అందుకే ఖచ్చితమైన సందేశం ఇప్పటికీ ముఖ్యం.
namespace దశను hook నుండి బయటకు తరలించండి
క్లయింట్ కలిగి ఉండకూడని అధికారం అవసరమయ్యే తయారీ దాని సొంత unitలో ఉండాలి. క్లయింట్కు ముందు నడిచి, తన ఫలితాన్ని ఉంచుకుని, కనెక్షన్కు ముందు క్రమబద్ధీకరించబడిన oneshot namespace దశకు అవసరమైనది ఇస్తుంది, ఆ హక్కులను టన్నెల్ ప్రక్రియకు ఇవ్వకుండా. తర్వాత క్లయింట్ ఆ unitను సూచిస్తుంది, తన up hook నుండి స్క్రిప్ట్ను పిలవడం బదులు.
క్రింది టెంప్లేట్ ఒక ప్రారంభ ఆకృతి, చదవకుండా వర్తించేది కాదు. అధికారం ఉన్న చోట తయారీని ఉంచి టన్నెల్ 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లను పునఃప్రారంభించండి, విఫలమైన ఆపరేషన్ను అమలు చేయండి, మరియు దాని ఫలితాన్ని మార్పుకు ముందు సేవ్ చేసిన జర్నల్ లైన్తో పోల్చండి. hook మళ్లీ ఎప్పుడూ నడవని స్థితిలో ప్రారంభమయ్యే 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చివరి లైన్ చదవడం బదులు తిరస్కరణలను లెక్కించండి, ఎందుకంటే hook విఫలమై, మళ్లీ ప్రయత్నించి విజయవంతం కావచ్చు, హద్దు కదిలిందా అని సంఖ్య మాత్రమే చూపుతుంది. drop-inలో మీరు సడలించిన ఆదేశాన్ని మరియు కారణాన్ని పేర్కొనే వ్యాఖ్యను వదిలేయండి, ఎందుకంటే తదుపరి అప్గ్రేడ్ మీ కాన్ఫిగరేషన్ను ప్యాకేజీ డిఫాల్ట్తో పోలుస్తుంది. ప్రతి రక్షణ నిలిపివేయబడిన తర్వాత మాత్రమే ప్రారంభమయ్యే unit సరిచేయబడలేదు.