VPN-ը միացված է, ներքին վահանակը բացվում է բրաուզերում, և Python-ի սկրիպտը դեռ պրոքսիի սխալ է արձակում։ Այդ պատկերում թունելի հետ ոչինչ սխալ չէ. ինտերպրետատորը պրոքսիի հասցե է կարդում իր իսկ միջավայրից և հարցումն ուղարկում այնտեղ։ Այս ուղեցույցը կարդում է այն միջավայրը, որը պրոցեսը իրականում տեսնում է, կիրառում է ամենանեղ բացառումը և միայն դրանից հետո դիտարկում է հստակ սեսիայի քաղաքականություն։ Ամեն քայլ ավարտվում է հրամանով, որի ելքը որոշում է՝ շարունակե՞լ եք։

Կարդացեք այն միջավայրը, որը պրոցեսը իրականում տեսնում է

Աշխատասեղանի պրոքսիի կարգավորումները, shell-ի արտահանումները և systemd-ի միավորի Environment= տողերը երեք տարբեր աղբյուր են, և Requests-ը կարդում է միայն վերջինը, որը ժառանգում է։ Գործարկեք ներքևի ախտորոշումը նույն shell-ում, կոնտեյներում կամ միավորում, որը գործարկում է ձախողված սկրիպտը, ոչ թե ձեր ինտերակտիվ տերմինալում։ Ձեր մուտքի shell-ում արտահանված փոփոխականը անտեսանելի է կոնտեյների պրոցեսի համար, և այդ բացը բացատրում է ոչ մի տեղից հայտնված պրոքսիի մասին բազում հաղորդումները։ Երկու հրամանները տպում են նույն տվյալները տարբեր մանրամասնության մակարդակով։

env | grep -i -E 'proxy|requests_ca_bundle|curl_ca_bundle'
python3 -c "import os;[print(k,'=',v) for k,v in sorted(os.environ.items()) if 'proxy' in k.lower()]"

Կարդացվում են յուրաքանչյուր փոփոխականի երկու ուղղագրությունները, և կրկնօրինակ գրառումները կիրառվում են այն հաջորդականությամբ, որով պրոցեսը ստացել է դրանք, ուստի հնացած HTTP_PROXY-ը կարող է վերագրել հենց նոր արտահանած արժեքը։ CA-փաթեթի փոփոխականներն այստեղ նույնպես կարևոր են, որովհետև դրանք փոխում են, թե verify-ը ինչի է լուծվում՝ չհայտնվելով կոդում ոչ մի տեղ։ Եթե ելքը դատարկ է, միջավայրը ձեր խնդիրը չէ, և կարող եք դադարել կարդալ այս բաժինը։ Եթե այն թվարկում է պրոքսի, որը չեք ճանաչում, գտեք այն սահմանող ֆայլը կամ միավորը՝ նախքան որևէ բան փոխելը։

Հարցրեք Requests-ին, թե ինչ կանի որոշակի URL-ի հետ։ Այս կանչը ցույց է տալիս այդ հարցման միացված պրոքսիի, verify-ի և cert-ի արժեքները՝ առանց փաթեթ ուղարկելու։

python3 -c "import requests;s=requests.Session();print(s.merge_environment_settings('https://api.corp.example/status',{},None,None,None))"

Մասնավոր հոսթի համար ոչ դատարկ proxies գրառումը ձեր պատասխանն է, և տպված verify արժեքը ասում է, թե որ CA-փաթեթին հարցումը կվստահեր։ Եթե երկուսն էլ ճիշտ են թվում, ձախողությունը ստեկում ավելի ուշ է, և պետք է անցնեք ստուգման բաժին։ Մի գուշակեք կոդից. միացումը կատարվում է յուրաքանչյուր հարցման համար, դրա համար էլ մեկ սեսիան կարող է տարբեր կերպ վարվել երկու հոսթի հետ։

Բացառեք մասնավոր հոսթը, նախքան որևէ բան անջատելը

Երբ պրոքսին իսկապես անհրաժեշտ է այլ նպատակակետերի համար, նեղ լուծումը այս հոսթի բացառումն է։ Ավելացրեք գոյություն ունեցող ցանկին, փոխարենը չփոխարինեք այն, որովհետև NO_PROXY-ը ջնջելը կործանում է ցանկացած այլ ներքին նպատակակետ, որը հենվել էր դրա վրա։ Ներքևի հրամանները ավելացնում են գրառումը և հետո հարցնում Requests-ին՝ արդյոք շրջանցումը գործում է։

export NO_PROXY="${NO_PROXY:+$NO_PROXY,}api.corp.example,.corp.example"
python3 -c "import requests;print(requests.utils.should_bypass_proxies('https://api.corp.example/status',None))"

Համապատասխանեցումը հոսթի վերջածանցով է, ուստի .corp.example-ը ծածկում է ամբողջ դոմենը, մինչդեռ api.corp.example-ը՝ մեկ անուն։ Մերկ աստղանիշը անջատում է պրոքսին բոլոր հոսթերի համար և գրեթե երբեք այն չէ, ինչ ուզում է արտադրական աշխատանքը։ Արդյոք CIDR գրառումը հարգվում է, կախված է պատկերի Requests-ի և urllib3-ի տարբերակներից, ուստի փորձարկեք ճշգրիտ գրառումը՝ ենթադրելու փոխարեն, որ այն աշխատում է։ Ստուգեք should_bypass_proxies-ի արդյունքը իրական URL-ի համար, ոչ թե հիշողությունից մուտքագրած հոսթի անվան համար։

Երկու շերտերը մտքում առանձին պահեք։ HTTP պրոքսին շրջանցելը չի շրջանցում VPN-ը, որովհետև պրոքսիի որոշումը կայացվում է գրադարանում, իսկ թունելի որոշումը՝ միջուկի երթուղավորման աղյուսակում։

Անջատեք trust_env-ը միայն որպես գիտակցված սեսիայի քաղաքականություն

Եթե ամբողջ աշխատանքը պետք է անտեսի շրջակա կազմաձևը, կառուցեք սեսիան հստակորեն և գրանցեք որոշումը կոդում։ Սա քաղաքականություն է, ոչ թե շրջանցում, և տեղ ունի diff-ում, որը գրախոսը կտեսնի։ Ներքևի օրինակը պահպանում է ժամկետը, CA-ի հստակ ուղին և կարգավիճակի ստուգումը։

import requests

with requests.Session() as session:
    session.trust_env = False
    response = session.get(
        "https://api.corp.example/status",
        timeout=(5, 20),
        verify="/etc/ssl/certs/corp-ca.pem",
    )
    response.raise_for_status()

trust_env-ի անջատումը միանգամից փոխում է երեք վարքագիծ, և դրանցից միայն մեկն է պրոքսիի մասին։ Requests-ը դադարում է կարդալ .netrc հավատարմագրերը, և REQUESTS_CA_BUNDLE ու CURL_CA_BUNDLE փոփոխականները դադարում են ազդել verify-ի վրա, որն այնուհետև վերադառնում է փաթեթավորված վկայականների պահոցին։ Եթե ձեր կազմակերպությունը TLS-ը ավարտում է իր CA-ով, այդ վերադարձը բարձրացնում է ստուգման սխալ, որը կապ չունի հենց նոր կատարած փոփոխության հետ։ verify-ի հստակ փոխանցումն է, ինչը երկու ազդեցություններն առանձին է պահում։

Ինչ չպետք է անեք, դա է verify=False-ը դնել ստացված սխալը լռեցնելու համար։ Դա պրոքսիի սխալ կազմաձևը փոխանակում է չստուգված կապով և թաքցնում է վկայականի խնդիրը, որը բացառումը պետք է բացահայտեր։

Ստուգեք ձախողված շերտը և պահպանեք վերադարձի հնարավորություն

Երեք խափանումներ մատյանում նույն տեսքն ունեն և ոչ մի ընդհանրություն չունեն. պրոքսին, որը չի հասնում նպատակակետին, արձակում է ProxyError կամ վերադարձնում է 502, վստահության խնդիրը արձակում է SSLError, իսկ հավելվածի մերժումը վերադարձնում է 401 կամ 403։ Վերարտադրեք հարցումը Requests-ից դուրս՝ տեսնելու, թե որն ունեք։ Ներքևի հրամանները հեռացնում են պրոքսին, փորձարկում վկայականների շղթան և հետո կրկնում կանչը գրադարանի միջով։

curl -sv --noproxy '*' https://api.corp.example/status -o /dev/null
openssl s_client -connect api.corp.example:443 -servername api.corp.example </dev/null
python3 -c "import requests;r=requests.get('https://api.corp.example/status',timeout=10);print(r.status_code)"

Եթե curl կանչը հաջողվում է, իսկ Python-ի կանչը ձախողվում է, տարբերությունը դեռ միջավայրն է։ Եթե երկուսն էլ ձախողվում են TLS փուլում, պրոքսին երբեք խնդիրը չի եղել, և խնդիրը վկայականների շղթան է։ Եթե երկուսն էլ վերադարձնում են 401, հարցումը հասել է հավելվածին, և մնացած աշխատանքը նույնականացումն է։ Ձեր դիտարկած երեքից որը գրանցելը մեկ ժամ է խնայում հաջորդ մարդուն։

Վերադարձը մեկ տող է ցանկացած ուղղությամբ. հեռացրեք բացառումը կամ հետ շրջեք trust_env-ը։ Պահպանեք նախորդ NO_PROXY արժեքը, նախքան դրան ավելացնելը, և նախընտրեք փաթաթող սկրիպտ կամ միավորի մակարդակի Environment= գրառում այն արտահանումից, որն ապրում է միայն ձեր տերմինալի պատմության մեջ։ Երկու փոփոխություններն էլ տեսանելի են պրոցեսի միջավայրում, ուստի վերսկսումը սովորաբար վերադարձնում է ձեզ հին վարքագծին։

Ավարտեք՝ հաստատելով չորս բան. մասնավոր URL-ի միացված կարգավորումները պրոքսի չեն ցույց տալիս, վկայականը վավերացվում է նախատեսված CA-ի դեմ, հարցումը վերադարձնում է ձեր սպասած կարգավիճակը, և փոփոխությունը commit է արված վերարտադրելի տեղում։ Անբացատրելի միջավայրով կանաչ սկրիպտը ուղղում է, որը նորից կկոտրվի հաջորդ մեքենայում։ Այս ուղեցույցի հրամաններն են, որ պետք է տեղադրեք տոմսում։

Առնչվող հոդվածներ