કઈ systemd સેન્ડબોક્સે તમારા OpenVPN હૂકને નકારી કાઢ્યો તે કેવી રીતે શોધવું
હૂક root તરીકે ચાલે છે અને systemd હેઠળ નિષ્ફળ જાય છે, કારણ કે unit ઓછી ક્ષમતાઓ, નાનું /dev અને ફક્ત-વાંચન માટેના પાથ રાખે છે.
તમે હૂકને 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 ને mount અધિકારો જોઈએ જે TUN ઉપકરણ ક્યારેય વાપરતું નથી
એક જ હૂકમાં સરખા દેખાતા બે ક્રિયાઓની પરવાનગી પ્રોફાઇલ અલગ હોય છે. /dev/net/tun ખોલવા અને ઇન્ટરફેસ બનાવવા માટે નેટવર્ક વ્યવસ્થાપન અને તે નોડ સુધીની પહોંચ જરૂરી છે. નામવાળું નેટવર્ક namespace બનાવવા પણ mount કાર્ય જરૂરી છે, કારણ કે namespace સાધન નવું /sys દૃશ્ય mount કરે છે અને સ્ટેટ ડિરેક્ટરીને તેની જગ્યાએ બાંધે છે. અપસ્ટ્રીમ ક્લાયન્ટ unit જાણી જોઈને mount વ્યવસ્થાપનને તેના બાઉન્ડિંગ સેટની બહાર રાખે છે, તેથી namespace પગલું નકારાય છે, જ્યારે ટનલ પોતે કામ કર્યું હોત.
તેથી ઉપકરણ નોડ આપવાથી સ્ક્રિપ્ટ બચતી નથી. ઉપકરણ પરવાનગી એક પ્રશ્નનો જવાબ આપે છે, શું આ પ્રક્રિયા આ નોડ ખોલી શકે, અને namespace નો પ્રશ્ન બીજો છે. કંઈપણ પહોળું કરતાં પહેલાં નિષ્ફળ કૉલને તેની ક્ષમતા સાથે મેળવો.
તમારા શેલમાંની કસોટી અમર્યાદિત root પાસેની દરેક ક્ષમતા વારસામાં લે છે, અને unit તેની બાઉન્ડિંગ સેટે જે રાખ્યું તે વારસામાં લે છે. બંને રન અલગ પ્રયોગો છે જ્યારે બાઇનરી એકસમાન હોય તો પણ.
ઉપકરણો, સુરક્ષિત પાથ અને કાર્ય મર્યાદાઓ
નકારાયેલી ક્રિયા ખબર પડ્યા પછી, ત્રણ ડાયરેક્ટિવ જૂથો મોટાભાગની નિષ્ફળતાઓ સમજાવે છે. ઉપકરણોની પહોંચ નિયંત્રિત કરે છે PrivateDevices, જે બદલે /dev ને ન્યૂનતમ સ્યુડો-ઉપકરણ સમૂહથી, અને DevicePolicy સાથે DeviceAllow, જે નક્કી કરે છે કે cgroup શું પરવાનગી આપે છે. /dev/net/tun તે ન્યૂનતમ સમૂહનો ભાગ નથી, તેથી PrivateDevices=yes વાળું unit ઉપકરણ નીતિ શું કહે તે પછી પણ તેને ખોલી શકતું નથી.
ફાઇલસિસ્ટમ સુરક્ષા બીજા પ્રશ્નનો જવાબ આપે છે. ProtectHome=yes બનાવે છે /home, /root અને /run/user અગમ્ય, અને ProtectSystem=full બનાવે છે /usr, /boot અને /etc ફક્ત-વાંચન. તેથી પોતાની કન્ફિગરેશન ફાઇલની બાજુમાં લખતો હૂક તમારા શેલમાં કામ કરે છે અને unit હેઠળ નિષ્ફળ જાય છે, ગુમ થયેલી ક્ષમતા જેવા જ પરવાનગી સ્વરૂપ સાથે. લખી શકાય તેવું ઇનપુટ નીતિ માન્ય કરે તેવા પાથ પર ખસેડો, અથવા સાંકડી ReadWritePaths= એન્ટ્રી ઉમેરો.
સ્રોત મર્યાદાઓ ત્રીજું જૂથ છે, અને સૌથી ઓછું સ્પષ્ટ. TasksMax= મર્યાદિત કરે છે કે unit કેટલા કાર્યો બનાવી શકે, અને ફાઇલ-ડિસ્ક્રિપ્ટર મર્યાદા સોકેટ અને હેન્ડલ માટે એ જ રીતે વર્તે છે. મર્યાદા વટાવી ગયેલું ડિપ્લોયમેન્ટ પરવાનગી ભૂલને બદલે સ્રોત ભૂલ સાથે નિષ્ફળ જાય છે, અને તેથી ચોક્કસ સંદેશ હજી મહત્વનો છે.
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 દરેક રક્ષણ બંધ કર્યા પછી જ શરૂ થાય છે તે સુધારાયું નથી.