Android-ի VpnService-ը բացառման երթուղի չունի, և API կարդալու ոչ մի քանակություն չի ստեղծի այն։ Builder.addRoute() թունելին միշտ միայն նպատակակետեր է ավելացնում, ուստի LAN հատվածը տեղական պահելը նշանակում է, որ այդ հատվածը երբեք չի մտնում երթուղիների ցանկ։ Փոխարենը դուք ավելացնում եք հատվածի լրացումը՝ արտահայտված սովորական նախածանցերով։ Աշխատանքը թվաբանություն է, և այն ձախողվում է մի քանի կանխատեսելի տեղերում։

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

Սկսեք նրանից, ինչ թունելը պնդում է

0.0.0.0/0-ը addRoute()-ին փոխանցելը Android-ին ասում է, որ յուրաքանչյուր IPv4 նպատակակետ պատկանում է թունելին։ Այդ պատճառով շատ հաճախորդներ անկարող են թվում բաժանված թունելավորման համար. նրանք պահանջում են ամբողջ հասցեային տարածությունը և հետո փորձում են հանել դրանից։ Կառուցիչում ոչինչ չի հանում։ Ավելի կոնկրետ երթուղին այն ցանցի համար, որը ցանկանում էիք տեղական պահել, անում է մարդկանց սպասածի հակառակը, որովհետև ամենաերկար համընկնող նախածանցը հաղթում է, և այդ ցանցը հայտնվում է թունելի ներսում։

Երթուղիների ցանկը ողջ քաղաքականությունն է։ Դրա հետևում նպատակակետով վետո չկա, և Builder-ի տեղեկատուն չի թվարկում ոչ մի մեթոդ, որը կտրամադրեր այն։

Գեներացրեք լրացումը նախածանցների թվաբանությունից

Բացառված նախածանցի լրացումը նրա քույր-եղբայրների բազմությունն է հասցեների ծառի արմատ տանող ճանապարհին։ 1-ից մինչև բացառված երկարությունը յուրաքանչյուր երկարության համար վերցրեք այդ երկարության բլոկը, որը պարունակում է ձեր նախածանցը, շրջեք նախածանցի անմիջապես ներքևի բիթը և տվեք արդյունքը։ Դա վերացական է հնչում, մինչև չգործարկեք։

10.0.0.0/8-ի բացառումը տալիս է ութ երթուղի. 128.0.0.0/1, 64.0.0.0/2, 32.0.0.0/3, 16.0.0.0/4, 0.0.0.0/5, 12.0.0.0/6, 8.0.0.0/7, 11.0.0.0/8։ Նրանցից ոչ մեկը չի պարունակում 10.0.0.0/8, և միասին նրանք ծածկում են մնացած ամեն ինչ։

Ութ տող գեներացնում են այդ ցանկը ցանկացած նախածանցի համար՝

import ipaddress
def complement(addr, length):
    base = int(ipaddress.IPv4Address(addr))
    out = []
    for k in range(1, length + 1):
        block = base & (0xFFFFFFFF << (32 - k))
        sibling = block ^ (1 << (32 - k))
        out.append(f"{ipaddress.IPv4Address(sibling)}/{k}")
    return out
print(complement("10.0.0.0", 8))

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

Ստուգեք հասցեների ընտանիքը և թունելի շրջանակը

IPv4 երթուղիները ոչինչ չեն անում IPv6-ի համար։ Եթե թունելը պահանջում է IPv6 հասցե, ապա IPv6 LAN նախածանցին պետք է իր սեփական լրացումը՝ գեներացված նույն թվաբանությամբ 128 բիթի վրա։ Հաճախ հանդիպող պատճառը, թե ինչու բացառումը թղթի վրա աշխատում է, մինչ տեղական սարքը մնում է անհասանելի, սա է. հոսթին հասել են IPv6-ով, և միայն IPv4-ն է կտրվել։ Ստուգեք երկու ընտանիքներն էլ՝ նախքան եզրակացնելը, որ մաթեմատիկան սխալ է։

Շրջանակը ստուգման մյուս կեսն է։ Android-ը հետևում է երթուղավորմանը ըստ ցանցի և ըստ հավելվածի, ուստի նույն նախածանցը կարող է թունելով գնալ մեկ հավելվածի համար և ուղիղ լինել մյուսի համար՝ կախված նրանից, թե ինչպես է հայտարարվել VPN-ը։

Տեղադրեք DNS-ի և ըստ հավելվածի կանոնները այնտեղ, որտեղ նրանք պատկանում են

Երթուղիների բացառումները չեն փոխում լուծիչը։ Տեղական հոսթի անունը դեռ կարող է պատասխանվել թունելի DNS սերվերի կողմից, մինչ նրա հասցեն երթուղավորվում է տեղական, և անհամապատասխանությունը երևում է որպես անուն, որը լուծվում է մի բանի, ինչին LAN-ը չի կարող հասնել։ Սահմանեք լուծիչի քաղաքականությունը գիտակցաբար՝ որոնման դոմենով կամ բաժանված DNS կանոնով։ Մի՛ ենթադրեք, որ երթուղիները որոշել են դա ձեր փոխարեն։

addDisallowedApplication()-ը մեկ հավելված դուրս է պահում թունելից. այն նպատակակետ դուրս չի պահում ներսում մնացող հավելվածների համար։ protect()-ը թույլ է տալիս ձեր բացած սոքեթին շրջանցել թունելը, և այդպես թունելը խուսափում է սեփական տրանսպորտը բռնելուց։ Ոչ մեկը չի փոխարինում լրացմանը։

Ստուգեք որոնմամբ, ոչ ձեր սեփական ցանկով

Երբ թունելը բարձրացված է, հարցրեք սարքին, թե ուր է հասցեն իրականում գնում՝ ձեր կառուցած ցանկը նորից կարդալու փոխարեն։ iproute2 ունեցող կառուցվածքում adb shell ip route get 10.1.2.3-ը նշում է այն ինտերֆեյսը, որն ընտրել է միջուկը։ Գործարկեք նույն հրամանը հանրային հասցեի համար և հաստատեք, որ այն նշում է թունելը։

Եվս երկու ստուգում փակում են շրջանը։ Նախ լուծեք տեղական անուն, ապա գործարկեք adb shell ip route get-ը լուծված հասցեի վրա և պահանջեք ինտերֆեյս, որը թունելը չէ, որովհետև հաջող adb shell ping -c 1 host.lan-ը ապացուցում է հասանելիությունը, ոչ ճանապարհը։ Կրկնեք հասցեների ընտանիքի թեստը IPv6-ի վրա, եթե թունելը պահանջում է մեկը։ Թեստավորեք ձեր թողարկած API մակարդակում, որովհետև այն, թե ինչպես VPN ցանցերը ներկայացվում են երթուղավորման աղյուսակին, փոխվել է թողարկումների ընթացքում։ Թղթի վրա ճիշտ թվացող երթուղիների ցանկը և սխալ ինտերֆեյս ընտրող որոնումը տարբեր վրիպակներ են, և միայն երկրորդն է հասնում օգտատերերին։

Եթե բացառումների ցանկը շարունակում է աճել, դադարեցրեք երթուղիներ գեներացնելը և վերահամարակալեք հեռավոր ցանցը կամ փոխարենը նեղացրեք թունելը։ Գեներատորը բացակայող API-ի շրջանցում է, ոչ նախագծման գործիք։

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