Refactor VPN proxy client implementation
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
export const CONNECTIVITY_IP_SOURCES = Object.freeze([
|
||||
{ id: 'cloudflare', label: 'Cloudflare', family: 4, url: 'https://www.cloudflare.com/cdn-cgi/trace' },
|
||||
{ id: 'ipify', label: 'ipify', family: 4, url: 'https://api.ipify.org' },
|
||||
{ id: 'aws', label: 'AWS', family: 4, url: 'https://checkip.amazonaws.com' },
|
||||
{ id: 'icanhazip', label: 'icanhazip', family: 4, url: 'https://icanhazip.com' },
|
||||
{ id: 'ifconfig-me', label: 'ifconfig.me', family: 4, url: 'https://ifconfig.me/ip' },
|
||||
{ id: 'yandex-internet', label: 'Яндекс Интернетометр', family: 4, url: 'https://yandex.ru/internet/' },
|
||||
{ id: 'ipify-v6', label: 'ipify IPv6', family: 6, url: 'https://api6.ipify.org' },
|
||||
]);
|
||||
|
||||
export const CONNECTIVITY_SITES = Object.freeze([
|
||||
{ id: 'google', label: 'Google', url: 'https://www.google.com/generate_204' },
|
||||
{ id: 'youtube', label: 'YouTube', url: 'https://www.youtube.com/generate_204' },
|
||||
{ id: 'instagram', label: 'Instagram', url: 'https://www.instagram.com/' },
|
||||
{ id: 'speedtest', label: 'Speedtest', url: 'https://www.speedtest.net/' },
|
||||
{ id: 'yandex', label: 'Яндекс Интернетометр', url: 'https://yandex.ru/internet/' },
|
||||
{ id: '2ip', label: '2IP', url: 'https://2ip.ru/' },
|
||||
]);
|
||||
|
||||
export const MAX_CUSTOM_DIAGNOSTIC_SERVICES = 5;
|
||||
|
||||
export interface ConnectivitySiteResult {
|
||||
id: string;
|
||||
label: string;
|
||||
status: string;
|
||||
httpStatus?: number | null;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export interface ConnectivityPathResult {
|
||||
available?: boolean;
|
||||
internetAvailable: boolean;
|
||||
ipv4: { addresses: string[]; [key: string]: unknown };
|
||||
ipv6: string | null;
|
||||
sites: ConnectivitySiteResult[];
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export function assessConnectivity(direct: ConnectivityPathResult, vpn: ConnectivityPathResult) {
|
||||
const comparisons = direct.sites.map(({ id, label }) => {
|
||||
const directSite = direct.sites.find((site) => site.id === id);
|
||||
const vpnSite = vpn.sites?.find((site) => site.id === id);
|
||||
let assessment = 'inconclusive';
|
||||
if (!vpn.available) assessment = 'not-tested';
|
||||
else if (directSite?.status === 'available' && vpnSite?.status === 'available') {
|
||||
assessment = 'available';
|
||||
} else if (
|
||||
directSite?.status === 'responded'
|
||||
&& [403, 451].includes(Number(directSite.httpStatus))
|
||||
&& vpnSite?.status === 'available'
|
||||
) assessment = 'likely-direct-restriction';
|
||||
else if (
|
||||
directSite?.status === 'unavailable'
|
||||
&& vpnSite?.status === 'available'
|
||||
&& direct.internetAvailable
|
||||
) {
|
||||
assessment = 'likely-direct-restriction';
|
||||
} else if (directSite?.status === 'available' && vpnSite?.status !== 'available') {
|
||||
assessment = 'vpn-problem';
|
||||
} else if (directSite?.status === 'unavailable' && vpnSite?.status === 'unavailable') {
|
||||
assessment = 'unavailable';
|
||||
}
|
||||
return { id, label, assessment, direct: directSite, vpn: vpnSite || null };
|
||||
});
|
||||
const directAddresses = [...direct.ipv4.addresses, direct.ipv6].filter(Boolean);
|
||||
const vpnAddresses = [...(vpn.ipv4?.addresses || []), vpn.ipv6].filter(Boolean);
|
||||
const sameEgress = directAddresses.some((address) => vpnAddresses.includes(address));
|
||||
let summary = 'inconclusive';
|
||||
if (!vpn.available) summary = 'vpn-off';
|
||||
else if (!direct.internetAvailable && !vpn.internetAvailable) summary = 'offline';
|
||||
else if (!direct.internetAvailable && vpn.internetAvailable) summary = 'direct-offline';
|
||||
else if (direct.internetAvailable && !vpn.internetAvailable) summary = 'vpn-problem';
|
||||
else if (comparisons.some((item) => item.assessment === 'likely-direct-restriction')) {
|
||||
summary = 'likely-direct-restriction';
|
||||
} else if (sameEgress) summary = 'same-ip';
|
||||
else if (comparisons.every((item) => item.assessment === 'available')) summary = 'available';
|
||||
return { summary, sameEgress, comparisons };
|
||||
}
|
||||
Reference in New Issue
Block a user