[{"data":1,"prerenderedAt":5366},["ShallowReactive",2],{"navLinks":3,"sidebar_docs_navigation_\u002Fblog\u002Fcombating-residential-proxies":124,"navigation":140,"navLinks_footer":181,"\u002Fblog\u002Fcombating-residential-proxies_page":211,"\u002Fblog\u002Fcombating-residential-proxies":3062},{"id":4,"extension":5,"links":6,"meta":121,"stem":122,"__hash__":123},"navigationMenu\u002Fnavigation.json","json",[7,57,62,103],{"label":8,"icon":9,"nested":10,"children":11},"API Products","i-lucide-box",true,[12,17,22,27,32,37,42,47,52],{"label":13,"to":14,"description":15,"icon":16},"Full IP Lookup","\u002Ffull-ip-lookup","Enrich any IP with complete intelligence","i-lucide-globe",{"label":18,"to":19,"description":20,"icon":21},"Proxy & VPN Detection","\u002Fproxy-vpn-detection","Identify proxies and VPN networks","i-lucide-shield-alert",{"label":23,"to":24,"description":25,"icon":26},"Tor Exit Nodes","\u002Ftor-exit-nodes","Block Tor anonymity network traffic","i-lucide-eye-off",{"label":28,"to":29,"description":30,"icon":31},"Granular Geolocation","\u002Fgranular-geolocation","Highly accurate location mapping","i-lucide-map-pin",{"label":33,"to":34,"description":35,"icon":36},"Threat Scoring System","\u002Fthreat-scoring-system","Unified traffic risk score","i-lucide-activity",{"label":38,"to":39,"description":40,"icon":41},"ASN & Carrier Data","\u002Fasn-carrier-data","Identify autonomous systems","i-lucide-server",{"label":43,"to":44,"description":45,"icon":46},"Disposable Email Check","\u002Fdisposable-email-check","Detect temporary email domains","i-lucide-mail",{"label":48,"to":49,"description":50,"icon":51},"User Agent Parser","\u002Fuser-agent-bot-parser","Parse messy HTTP headers","i-lucide-bot",{"label":53,"to":54,"description":55,"icon":56},"Verified Bots","\u002Fverified-bots-crawlers","Identify legitimate search engine crawlers","i-lucide-check-circle",{"label":58,"to":59,"icon":60,"nested":61},"Pricing","\u002Fpricing","i-lucide-credit-card",false,{"label":63,"to":64,"icon":65,"nested":10,"children":66},"Docs","\u002Fdocs","i-lucide-book-open",[67,71,76,81,86,91,95,98],{"label":68,"to":64,"description":69,"icon":70},"Getting Started","Learn how to setup and use IP Shield","i-lucide-rocket",{"label":72,"to":73,"description":74,"icon":75},"All Endpoints","\u002Fdocs\u002Fendpoints\u002Femail-domain-check","Reference for all IP Shield REST API endpoints","i-lucide-plug",{"label":77,"to":78,"description":79,"icon":80},"Network API","\u002Fdocs\u002Fendpoints\u002Fnetwork","Network intelligence and routing data","i-lucide-network",{"label":82,"to":83,"description":84,"icon":85},"Summary API","\u002Fdocs\u002Fendpoints\u002Fsummary","Full IP intelligence summary","i-lucide-bar-chart-2",{"label":87,"to":88,"description":89,"icon":90},"Lookup IP API","\u002Fdocs\u002Fendpoints\u002Flookup-ip","Single IP data lookup","i-lucide-search",{"label":92,"to":93,"description":94,"icon":31},"Geo Check API","\u002Fdocs\u002Fendpoints\u002Fgeo-check","Check geographic location",{"label":96,"to":73,"description":97,"icon":46},"Email Domain Check API","Verify disposable email domains",{"label":99,"to":100,"description":101,"icon":102},"User Agent Check API","\u002Fdocs\u002Fendpoints\u002Fuser-agent-check","Detect malicious user agents","i-lucide-monitor",{"label":104,"icon":105,"nested":10,"children":106},"Resources","i-lucide-library",[107,112,117],{"label":108,"to":109,"icon":110,"description":111},"About Us","\u002Fabout","i-lucide-info","Learn more about IP Shield and our mission",{"label":113,"to":114,"icon":115,"description":116},"Blog","\u002Fblog","i-lucide-newspaper","Latest news, updates, and security articles",{"label":118,"to":119,"description":120,"icon":46},"Contact Us","\u002Fcontact","Get in touch with our support team",{},"navigation","OH-Zj4UmYqVQJC8Ts6f4KeKRzXJYi5trdK22JpX9Y0Q",[125],{"title":113,"path":114,"stem":126,"children":127,"page":61},"blog",[128,132,136],{"title":129,"path":130,"stem":131},"Combating Residential Proxies and VPNs in Modern Applications","\u002Fblog\u002Fcombating-residential-proxies","blog\u002Fcombating-residential-proxies",{"title":133,"path":134,"stem":135},"Ultimate Guide to Trading Automation & Volume Strategies","\u002Fblog\u002Fintroducing-ip-shield","blog\u002Fintroducing-ip-shield",{"title":137,"path":138,"stem":139},"The Evolution of Bot Management and User Agent Parsing","\u002Fblog\u002Fthe-evolution-of-bot-management","blog\u002Fthe-evolution-of-bot-management",[141],{"title":63,"path":64,"stem":142,"children":143},"docs",[144,147,164],{"title":145,"path":64,"stem":146},"Introduction","docs\u002Findex",{"title":148,"path":149,"stem":150,"children":151,"page":61},"Credit & Authorization","\u002Fdocs\u002Fcredits-and-auth","docs\u002Fcredits-and-auth",[152,156,160],{"title":153,"path":154,"stem":155},"Authentication","\u002Fdocs\u002Fcredits-and-auth\u002Fauth","docs\u002Fcredits-and-auth\u002Fauth",{"title":157,"path":158,"stem":159},"Credits & Usage","\u002Fdocs\u002Fcredits-and-auth\u002Fcredits-usage","docs\u002Fcredits-and-auth\u002Fcredits-usage",{"title":161,"path":162,"stem":163},"Rate Limits","\u002Fdocs\u002Fcredits-and-auth\u002Frate-limits","docs\u002Fcredits-and-auth\u002Frate-limits",{"title":165,"path":166,"stem":167,"children":168,"page":61},"API Endpoints","\u002Fdocs\u002Fendpoints","docs\u002Fendpoints",[169,171,173,175,177,179],{"title":96,"path":73,"stem":170},"docs\u002Fendpoints\u002Femail-domain-check",{"title":92,"path":93,"stem":172},"docs\u002Fendpoints\u002Fgeo-check",{"title":87,"path":88,"stem":174},"docs\u002Fendpoints\u002Flookup-ip",{"title":77,"path":78,"stem":176},"docs\u002Fendpoints\u002Fnetwork",{"title":82,"path":83,"stem":178},"docs\u002Fendpoints\u002Fsummary",{"title":99,"path":100,"stem":180},"docs\u002Fendpoints\u002Fuser-agent-check",{"id":4,"extension":5,"links":182,"meta":210,"stem":122,"__hash__":123},[183,194,195,205],{"label":8,"icon":9,"nested":10,"children":184},[185,186,187,188,189,190,191,192,193],{"label":13,"to":14,"description":15,"icon":16},{"label":18,"to":19,"description":20,"icon":21},{"label":23,"to":24,"description":25,"icon":26},{"label":28,"to":29,"description":30,"icon":31},{"label":33,"to":34,"description":35,"icon":36},{"label":38,"to":39,"description":40,"icon":41},{"label":43,"to":44,"description":45,"icon":46},{"label":48,"to":49,"description":50,"icon":51},{"label":53,"to":54,"description":55,"icon":56},{"label":58,"to":59,"icon":60,"nested":61},{"label":63,"to":64,"icon":65,"nested":10,"children":196},[197,198,199,200,201,202,203,204],{"label":68,"to":64,"description":69,"icon":70},{"label":72,"to":73,"description":74,"icon":75},{"label":77,"to":78,"description":79,"icon":80},{"label":82,"to":83,"description":84,"icon":85},{"label":87,"to":88,"description":89,"icon":90},{"label":92,"to":93,"description":94,"icon":31},{"label":96,"to":73,"description":97,"icon":46},{"label":99,"to":100,"description":101,"icon":102},{"label":104,"icon":105,"nested":10,"children":206},[207,208,209],{"label":108,"to":109,"icon":110,"description":111},{"label":113,"to":114,"icon":115,"description":116},{"label":118,"to":119,"description":120,"icon":46},{},{"id":212,"title":129,"author":213,"authorGithub":214,"authorGithubUserName":215,"authorImg":216,"body":217,"date":3046,"description":3047,"extension":3048,"featured":10,"icon":3049,"image":3050,"meta":3051,"navigation":10,"path":130,"rawbody":3052,"readingTime":3053,"seo":3054,"stem":131,"tags":3055,"__hash__":3061},"blog\u002Fblog\u002Fcombating-residential-proxies.md","Sergio","https:\u002F\u002Fgithub.com\u002FSergo706","Sergo706","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F187537278?v=4",{"type":218,"value":219,"toc":3018},"minimark",[220,224,228,231,237,242,245,250,253,282,286,289,292,295,373,377,380,384,387,391,394,398,401,407,411,414,417,421,424,427,430,434,437,441,444,447,1508,1518,1522,1525,1962,1965,2237,2241,2244,2867,2873,2877,2884,2894,2898,2923,2934,2938,2941,2945,2948,2951,2955,2958,2961,2965,2968,2971,2998,3001,3005,3008,3011,3014],[221,222,129],"h1",{"id":223},"combating-residential-proxies-and-vpns-in-modern-applications",[225,226,227],"p",{},"Protecting modern web applications requires significantly more than just checking an IP address against a static blocklist. Attackers constantly evolve their techniques. They leverage residential proxies and commercial VPN networks to mask their true origin and bypass rate limits.",[225,229,230],{},"The security industry faces a continuous and escalating challenge. Traditional security layers struggle to differentiate between a legitimate user logging in from their home internet and an automated script routing traffic through a compromised residential proxy network. This comprehensive guide explores the mechanics of residential proxies, the economics driving their use, and the technical strategies you must implement to defend your infrastructure.",[232,233,234],"note",{},[225,235,236],{},"A residential proxy routes traffic through an actual residential internet connection. This makes the traffic appear as though it originates from a standard home user rather than a datacenter, effectively bypassing traditional IP-based filtering.",[238,239,241],"h2",{"id":240},"the-anatomy-of-the-threat-landscape","The Anatomy of the Threat Landscape",[225,243,244],{},"To effectively defend against a threat, you must first understand how it operates at a fundamental level. The proxy ecosystem is vast, complex, and highly commercialized.",[246,247,249],"h3",{"id":248},"types-of-ip-addresses-used-by-attackers","Types of IP Addresses Used by Attackers",[225,251,252],{},"Attackers utilize several categories of IP addresses, each with distinct characteristics and risk profiles:",[254,255,256,264,270,276],"ol",{},[257,258,259,263],"li",{},[260,261,262],"strong",{},"Datacenter IPs",": These are IP addresses assigned to massive server farms and cloud providers like AWS, Google Cloud, DigitalOcean, and Hetzner. They are cheap, fast, and highly available. However, they are also incredibly easy to detect and block. Legitimate consumers rarely browse the web from an AWS data center.",[257,265,266,269],{},[260,267,268],{},"Commercial VPNs",": Services like NordVPN, ExpressVPN, and ProtonVPN route user traffic through shared egress IPs. While often used by privacy-conscious individuals, attackers heavily abuse them to mask their geographic location and true identity.",[257,271,272,275],{},[260,273,274],{},"Residential Proxies",": These IPs belong to standard Internet Service Providers (ISPs) like Comcast, AT&T, and BT. They are attached to actual residential homes. Traffic originating from these IPs carries an inherently high reputation.",[257,277,278,281],{},[260,279,280],{},"Mobile Proxies",": Similar to residential proxies, but the IPs belong to cellular carriers (e.g., Verizon, T-Mobile, Vodafone). These are the most difficult to block because thousands of legitimate users often share a single mobile IP via Carrier-Grade NAT (CGNAT).",[246,283,285],{"id":284},"how-residential-proxy-networks-are-built","How Residential Proxy Networks are Built",[225,287,288],{},"Understanding how attackers acquire residential IPs is critical. They do not purchase these directly from ISPs. Instead, residential proxy networks are formed through various methods, many of which reside in an ethical gray area or are outright illegal.",[225,290,291],{},"Some networks operate legitimately by offering users free software or premium features in exchange for sharing their idle bandwidth. Users agree to the terms of service, effectively turning their home router or computer into an exit node for the proxy network.",[225,293,294],{},"However, many residential proxy networks are botnets built via malware. Attackers infect thousands of IoT devices, smart TVs, home routers, and personal computers. They then sell access to this compromised network to other malicious actors on the dark web or through shady proxy reselling platforms.",[296,297,302],"pre",{"className":298,"code":299,"language":300,"meta":301,"style":301},"language-mermaid shiki shiki-themes light-plus light-plus dracula","graph TD\n    A[Attacker \u002F Scraper Script] -->|Routes Traffic| B(Proxy Network Controller)\n    B --> C[Infected Smart TV]\n    B --> D[Compromised Router]\n    B --> E[User running 'Free' VPN Extension]\n    C -->|Requests| F[Your Application]\n    D -->|Requests| F[Your Application]\n    E -->|Requests| F[Your Application]\n    \n    style A fill:#ffcccc,stroke:#ff0000,stroke-width:2px\n    style F fill:#ccffcc,stroke:#00aa00,stroke-width:2px\n","mermaid","",[303,304,305,313,319,325,331,337,343,349,355,361,367],"code",{"__ignoreMap":301},[306,307,310],"span",{"class":308,"line":309},"line",1,[306,311,312],{},"graph TD\n",[306,314,316],{"class":308,"line":315},2,[306,317,318],{},"    A[Attacker \u002F Scraper Script] -->|Routes Traffic| B(Proxy Network Controller)\n",[306,320,322],{"class":308,"line":321},3,[306,323,324],{},"    B --> C[Infected Smart TV]\n",[306,326,328],{"class":308,"line":327},4,[306,329,330],{},"    B --> D[Compromised Router]\n",[306,332,334],{"class":308,"line":333},5,[306,335,336],{},"    B --> E[User running 'Free' VPN Extension]\n",[306,338,340],{"class":308,"line":339},6,[306,341,342],{},"    C -->|Requests| F[Your Application]\n",[306,344,346],{"class":308,"line":345},7,[306,347,348],{},"    D -->|Requests| F[Your Application]\n",[306,350,352],{"class":308,"line":351},8,[306,353,354],{},"    E -->|Requests| F[Your Application]\n",[306,356,358],{"class":308,"line":357},9,[306,359,360],{},"    \n",[306,362,364],{"class":308,"line":363},10,[306,365,366],{},"    style A fill:#ffcccc,stroke:#ff0000,stroke-width:2px\n",[306,368,370],{"class":308,"line":369},11,[306,371,372],{},"    style F fill:#ccffcc,stroke:#00aa00,stroke-width:2px\n",[238,374,376],{"id":375},"the-economic-incentives","The Economic Incentives",[225,378,379],{},"Why do attackers go through the trouble and expense of using residential proxies? The answer lies in the massive return on investment (ROI) available in digital fraud.",[246,381,383],{"id":382},"account-takeover-ato-and-credential-stuffing","Account Takeover (ATO) and Credential Stuffing",[225,385,386],{},"Attackers purchase massive databases of leaked usernames and passwords. They write scripts to test these credentials against your login endpoints. If they use a single datacenter IP, your rate-limiting rules block them after a few dozen attempts. By routing the requests through thousands of residential proxies, they stay under the rate-limit thresholds and blend in with regular login traffic.",[246,388,390],{"id":389},"e-commerce-scalping-and-inventory-hoarding","E-commerce Scalping and Inventory Hoarding",[225,392,393],{},"When highly anticipated products drop—such as limited-edition sneakers, concert tickets, or next-generation gaming consoles—scalping bots swarm the site. They use residential proxies to bypass per-IP purchase limits. Scalpers can generate millions of dollars in secondary market profits, easily justifying the cost of premium residential proxy subscriptions.",[246,395,397],{"id":396},"payment-fraud-and-carding","Payment Fraud and Carding",[225,399,400],{},"Attackers use stolen credit card information to purchase digital goods or physical items. They use residential proxies located in the same city or zip code as the stolen credit card's billing address. This geographic consistency easily bypasses simplistic fraud detection systems that flag long-distance mismatches.",[402,403,404],"warning",{},[225,405,406],{},"Blocking entire ISPs or geographic regions to stop these attacks often leads to unacceptable false positive rates. You lock out genuine customers while attempting to stop a handful of malicious actors.",[238,408,410],{"id":409},"utilizing-deep-network-intelligence","Utilizing Deep Network Intelligence",[225,412,413],{},"IP Shield resolves this challenge by providing deep network intelligence on every request. The platform analyzes the IP address and returns a comprehensive metadata payload. This includes VPN detection flags, proxy network associations, Tor exit node identification, and precise ASN details.",[225,415,416],{},"You use this intelligence to introduce adaptive friction into your user flows. Rather than outright blocking an IP, you challenge high-risk connections with a CAPTCHA, require multi-factor authentication (MFA), or flag the account for manual review.",[246,418,420],{"id":419},"the-role-of-the-autonomous-system-number-asn","The Role of the Autonomous System Number (ASN)",[225,422,423],{},"The Internet is a network of networks. An Autonomous System (AS) is a large network or group of networks that has a unified routing policy. Every AS is assigned an Autonomous System Number (ASN).",[225,425,426],{},"By evaluating the ASN, you determine the organization responsible for the IP address. If the ASN belongs to a known consumer ISP like \"Comcast Cable Communications,\" the traffic is likely residential. If the ASN belongs to \"DigitalOcean, LLC,\" the traffic is from a datacenter.",[225,428,429],{},"IP Shield provides the ASN data instantly. You filter traffic based on the network type. For example, you easily block all traffic originating from hosting providers on your consumer-facing login routes, while allowing cellular and residential networks to pass unhindered.",[238,431,433],{"id":432},"implementing-the-defense-in-code","Implementing the Defense in Code",[225,435,436],{},"Defending against residential proxies demands a dynamic security posture. You must integrate real-time intelligence into your edge compute layer or application backend. By doing so, you automatically filter out the noise and focus your resources on serving legitimate users.",[246,438,440],{"id":439},"nuxt-3-and-h3-implementation","Nuxt 3 and h3 Implementation",[225,442,443],{},"If you are using the modern Nuxt 3 stack, you integrate the IP Shield Network API directly into your server API routes or middleware. You evaluate the IP address before processing sensitive actions like logins, registrations, or checkouts.",[225,445,446],{},"Here is an extensive example of how you build a robust, production-ready login handler using Nuxt 3, handling edge cases, proxy headers, and implementing adaptive friction.",[296,448,453],{"className":449,"code":450,"filename":451,"language":452,"meta":301,"style":301},"language-typescript shiki shiki-themes light-plus light-plus dracula","import { IPShield } from '@ip-shield\u002Fsdk';\nimport { sendError, setResponseStatus, createError } from 'h3';\n\n\u002F\u002F Initialize the IP Shield SDK with your secure API key\nconst shield = new IPShield(process.env.IP_SHIELD_API_KEY);\n\nexport default defineEventHandler(async (event) => {\n  \u002F\u002F 1. Safely extract the client IP address\n  \u002F\u002F When behind a CDN or Load Balancer (Cloudflare, AWS ALB), the direct \n  \u002F\u002F connection IP belongs to the CDN. We must inspect the X-Forwarded-For header.\n  const ip = getRequestIP(event, { xForwardedFor: true });\n  \n  if (!ip) {\n    throw createError({\n      statusCode: 400,\n      statusMessage: 'Unable to determine client IP address'\n    });\n  }\n\n  const body = await readBody(event);\n  \n  \u002F\u002F 2. Perform the IP Intelligence Lookup\n  \u002F\u002F We use a try-catch block to ensure that if the IP Shield API is unreachable \n  \u002F\u002F due to network issues, we fail open or handle it gracefully rather than \n  \u002F\u002F blocking all user logins.\n  let networkData;\n  try {\n    networkData = await shield.network.lookup(ip);\n  } catch (err) {\n    console.error('IP Shield lookup failed, failing open for availability', err);\n    \u002F\u002F Proceed with standard authentication, but log the failure\n    return authenticateUser(body.email, body.password);\n  }\n  \n  \u002F\u002F 3. Analyze the Threat Vectors\n  const isHighRisk = networkData.isProxy || networkData.isVpn || networkData.isTor;\n  const isDatacenter = networkData.asn.type === 'hosting';\n  \n  \u002F\u002F 4. Execute the Security Policy\n  if (networkData.isTor) {\n    \u002F\u002F Tor traffic is almost exclusively malicious in an e-commerce context.\n    \u002F\u002F We block it outright.\n    setResponseStatus(event, 403);\n    return { \n      error: 'access_denied', \n      message: 'Connections from the Tor network are not permitted.' \n    };\n  }\n\n  if (isDatacenter) {\n    \u002F\u002F Legitimate users do not log in from AWS servers. This is likely a script.\n    setResponseStatus(event, 403);\n    return { \n      error: 'access_denied', \n      message: 'Datacenter IP ranges are not permitted. Please disable your VPN.' \n    };\n  }\n\n  if (isHighRisk) {\n    \u002F\u002F The IP belongs to a residential proxy or commercial VPN. \n    \u002F\u002F It might be a malicious actor, or it might be a privacy-conscious user.\n    \u002F\u002F We do NOT block them outright. Instead, we introduce adaptive friction.\n    setResponseStatus(event, 401);\n    return { \n      error: 'verification_required', \n      challengeType: 'mfa',\n      message: 'Unusual network detected. Please enter the code sent to your mobile device.' \n    };\n  }\n  \n  \u002F\u002F 5. If all checks pass, proceed with standard authentication\n  const authResult = await authenticateUser(body.email, body.password);\n  \n  if (!authResult.success) {\n    \u002F\u002F Even if the IP is safe, standard credential checks still apply\n    throw createError({\n      statusCode: 401,\n      statusMessage: 'Invalid credentials'\n    });\n  }\n\n  return {\n    success: true,\n    token: authResult.token,\n    user: authResult.user\n  };\n});\n","server\u002Fapi\u002Flogin.post.ts","typescript",[303,454,455,489,521,526,532,575,579,611,616,621,626,660,666,683,695,710,726,732,738,743,765,770,776,782,788,794,805,813,841,857,883,889,919,924,929,935,973,1007,1012,1018,1034,1040,1046,1063,1071,1089,1107,1113,1118,1123,1135,1141,1156,1163,1178,1194,1199,1204,1209,1221,1227,1233,1239,1255,1262,1278,1295,1311,1316,1321,1326,1332,1364,1369,1388,1394,1403,1415,1429,1434,1439,1444,1452,1464,1481,1496,1502],{"__ignoreMap":301},[306,456,457,461,465,469,472,475,479,483,486],{"class":308,"line":309},[306,458,460],{"class":459},"sZ328","import",[306,462,464],{"class":463},"sDd4n"," { ",[306,466,468],{"class":467},"sjsA6","IPShield",[306,470,471],{"class":463}," } ",[306,473,474],{"class":459},"from",[306,476,478],{"class":477},"sFkSl"," '",[306,480,482],{"class":481},"sFB1V","@ip-shield\u002Fsdk",[306,484,485],{"class":477},"'",[306,487,488],{"class":463},";\n",[306,490,491,493,495,498,501,504,506,509,511,513,515,517,519],{"class":308,"line":315},[306,492,460],{"class":459},[306,494,464],{"class":463},[306,496,497],{"class":467},"sendError",[306,499,500],{"class":463},", ",[306,502,503],{"class":467},"setResponseStatus",[306,505,500],{"class":463},[306,507,508],{"class":467},"createError",[306,510,471],{"class":463},[306,512,474],{"class":459},[306,514,478],{"class":477},[306,516,246],{"class":481},[306,518,485],{"class":477},[306,520,488],{"class":463},[306,522,523],{"class":308,"line":321},[306,524,525],{"emptyLinePlaceholder":10},"\n",[306,527,528],{"class":308,"line":327},[306,529,531],{"class":530},"sghk6","\u002F\u002F Initialize the IP Shield SDK with your secure API key\n",[306,533,534,538,542,546,550,554,557,560,563,566,568,572],{"class":308,"line":333},[306,535,537],{"class":536},"sl46w","const",[306,539,541],{"class":540},"s3JHE"," shield",[306,543,545],{"class":544},"saOXh"," =",[306,547,549],{"class":548},"sakC6"," new",[306,551,553],{"class":552},"sHOzp"," IPShield",[306,555,556],{"class":463},"(",[306,558,559],{"class":467},"process",[306,561,562],{"class":463},".",[306,564,565],{"class":467},"env",[306,567,562],{"class":463},[306,569,571],{"class":570},"sPzPf","IP_SHIELD_API_KEY",[306,573,574],{"class":463},");\n",[306,576,577],{"class":308,"line":339},[306,578,525],{"emptyLinePlaceholder":10},[306,580,581,584,587,590,592,595,598,602,605,608],{"class":308,"line":345},[306,582,583],{"class":459},"export",[306,585,586],{"class":459}," default",[306,588,589],{"class":552}," defineEventHandler",[306,591,556],{"class":463},[306,593,594],{"class":536},"async",[306,596,597],{"class":463}," (",[306,599,601],{"class":600},"sygFZ","event",[306,603,604],{"class":463},") ",[306,606,607],{"class":536},"=>",[306,609,610],{"class":463}," {\n",[306,612,613],{"class":308,"line":351},[306,614,615],{"class":530},"  \u002F\u002F 1. Safely extract the client IP address\n",[306,617,618],{"class":308,"line":357},[306,619,620],{"class":530},"  \u002F\u002F When behind a CDN or Load Balancer (Cloudflare, AWS ALB), the direct \n",[306,622,623],{"class":308,"line":363},[306,624,625],{"class":530},"  \u002F\u002F connection IP belongs to the CDN. We must inspect the X-Forwarded-For header.\n",[306,627,628,631,634,636,639,641,643,646,649,653,657],{"class":308,"line":369},[306,629,630],{"class":536},"  const",[306,632,633],{"class":540}," ip",[306,635,545],{"class":544},[306,637,638],{"class":552}," getRequestIP",[306,640,556],{"class":463},[306,642,601],{"class":467},[306,644,645],{"class":463},", { ",[306,647,648],{"class":467},"xForwardedFor",[306,650,652],{"class":651},"s34zl",":",[306,654,656],{"class":655},"sjR7W"," true",[306,658,659],{"class":463}," });\n",[306,661,663],{"class":308,"line":662},12,[306,664,665],{"class":463},"  \n",[306,667,669,672,674,677,680],{"class":308,"line":668},13,[306,670,671],{"class":459},"  if",[306,673,597],{"class":463},[306,675,676],{"class":544},"!",[306,678,679],{"class":467},"ip",[306,681,682],{"class":463},") {\n",[306,684,686,689,692],{"class":308,"line":685},14,[306,687,688],{"class":459},"    throw",[306,690,691],{"class":552}," createError",[306,693,694],{"class":463},"({\n",[306,696,698,701,703,707],{"class":308,"line":697},15,[306,699,700],{"class":467},"      statusCode",[306,702,652],{"class":651},[306,704,706],{"class":705},"spgvN"," 400",[306,708,709],{"class":463},",\n",[306,711,713,716,718,720,723],{"class":308,"line":712},16,[306,714,715],{"class":467},"      statusMessage",[306,717,652],{"class":651},[306,719,478],{"class":477},[306,721,722],{"class":481},"Unable to determine client IP address",[306,724,725],{"class":477},"'\n",[306,727,729],{"class":308,"line":728},17,[306,730,731],{"class":463},"    });\n",[306,733,735],{"class":308,"line":734},18,[306,736,737],{"class":463},"  }\n",[306,739,741],{"class":308,"line":740},19,[306,742,525],{"emptyLinePlaceholder":10},[306,744,746,748,751,753,756,759,761,763],{"class":308,"line":745},20,[306,747,630],{"class":536},[306,749,750],{"class":540}," body",[306,752,545],{"class":544},[306,754,755],{"class":459}," await",[306,757,758],{"class":552}," readBody",[306,760,556],{"class":463},[306,762,601],{"class":467},[306,764,574],{"class":463},[306,766,768],{"class":308,"line":767},21,[306,769,665],{"class":463},[306,771,773],{"class":308,"line":772},22,[306,774,775],{"class":530},"  \u002F\u002F 2. Perform the IP Intelligence Lookup\n",[306,777,779],{"class":308,"line":778},23,[306,780,781],{"class":530},"  \u002F\u002F We use a try-catch block to ensure that if the IP Shield API is unreachable \n",[306,783,785],{"class":308,"line":784},24,[306,786,787],{"class":530},"  \u002F\u002F due to network issues, we fail open or handle it gracefully rather than \n",[306,789,791],{"class":308,"line":790},25,[306,792,793],{"class":530},"  \u002F\u002F blocking all user logins.\n",[306,795,797,800,803],{"class":308,"line":796},26,[306,798,799],{"class":536},"  let",[306,801,802],{"class":467}," networkData",[306,804,488],{"class":463},[306,806,808,811],{"class":308,"line":807},27,[306,809,810],{"class":459},"  try",[306,812,610],{"class":463},[306,814,816,819,821,823,825,827,830,832,835,837,839],{"class":308,"line":815},28,[306,817,818],{"class":467},"    networkData",[306,820,545],{"class":544},[306,822,755],{"class":459},[306,824,541],{"class":467},[306,826,562],{"class":463},[306,828,829],{"class":467},"network",[306,831,562],{"class":463},[306,833,834],{"class":552},"lookup",[306,836,556],{"class":463},[306,838,679],{"class":467},[306,840,574],{"class":463},[306,842,844,847,850,852,855],{"class":308,"line":843},29,[306,845,846],{"class":463},"  } ",[306,848,849],{"class":459},"catch",[306,851,597],{"class":463},[306,853,854],{"class":467},"err",[306,856,682],{"class":463},[306,858,860,863,865,868,870,872,875,877,879,881],{"class":308,"line":859},30,[306,861,862],{"class":467},"    console",[306,864,562],{"class":463},[306,866,867],{"class":552},"error",[306,869,556],{"class":463},[306,871,485],{"class":477},[306,873,874],{"class":481},"IP Shield lookup failed, failing open for availability",[306,876,485],{"class":477},[306,878,500],{"class":463},[306,880,854],{"class":467},[306,882,574],{"class":463},[306,884,886],{"class":308,"line":885},31,[306,887,888],{"class":530},"    \u002F\u002F Proceed with standard authentication, but log the failure\n",[306,890,892,895,898,900,903,905,908,910,912,914,917],{"class":308,"line":891},32,[306,893,894],{"class":459},"    return",[306,896,897],{"class":552}," authenticateUser",[306,899,556],{"class":463},[306,901,902],{"class":467},"body",[306,904,562],{"class":463},[306,906,907],{"class":467},"email",[306,909,500],{"class":463},[306,911,902],{"class":467},[306,913,562],{"class":463},[306,915,916],{"class":467},"password",[306,918,574],{"class":463},[306,920,922],{"class":308,"line":921},33,[306,923,737],{"class":463},[306,925,927],{"class":308,"line":926},34,[306,928,665],{"class":463},[306,930,932],{"class":308,"line":931},35,[306,933,934],{"class":530},"  \u002F\u002F 3. Analyze the Threat Vectors\n",[306,936,938,940,943,945,947,949,952,955,957,959,962,964,966,968,971],{"class":308,"line":937},36,[306,939,630],{"class":536},[306,941,942],{"class":540}," isHighRisk",[306,944,545],{"class":544},[306,946,802],{"class":467},[306,948,562],{"class":463},[306,950,951],{"class":467},"isProxy",[306,953,954],{"class":544}," ||",[306,956,802],{"class":467},[306,958,562],{"class":463},[306,960,961],{"class":467},"isVpn",[306,963,954],{"class":544},[306,965,802],{"class":467},[306,967,562],{"class":463},[306,969,970],{"class":467},"isTor",[306,972,488],{"class":463},[306,974,976,978,981,983,985,987,990,992,995,998,1000,1003,1005],{"class":308,"line":975},37,[306,977,630],{"class":536},[306,979,980],{"class":540}," isDatacenter",[306,982,545],{"class":544},[306,984,802],{"class":467},[306,986,562],{"class":463},[306,988,989],{"class":467},"asn",[306,991,562],{"class":463},[306,993,994],{"class":467},"type",[306,996,997],{"class":544}," ===",[306,999,478],{"class":477},[306,1001,1002],{"class":481},"hosting",[306,1004,485],{"class":477},[306,1006,488],{"class":463},[306,1008,1010],{"class":308,"line":1009},38,[306,1011,665],{"class":463},[306,1013,1015],{"class":308,"line":1014},39,[306,1016,1017],{"class":530},"  \u002F\u002F 4. Execute the Security Policy\n",[306,1019,1021,1023,1025,1028,1030,1032],{"class":308,"line":1020},40,[306,1022,671],{"class":459},[306,1024,597],{"class":463},[306,1026,1027],{"class":467},"networkData",[306,1029,562],{"class":463},[306,1031,970],{"class":467},[306,1033,682],{"class":463},[306,1035,1037],{"class":308,"line":1036},41,[306,1038,1039],{"class":530},"    \u002F\u002F Tor traffic is almost exclusively malicious in an e-commerce context.\n",[306,1041,1043],{"class":308,"line":1042},42,[306,1044,1045],{"class":530},"    \u002F\u002F We block it outright.\n",[306,1047,1049,1052,1054,1056,1058,1061],{"class":308,"line":1048},43,[306,1050,1051],{"class":552},"    setResponseStatus",[306,1053,556],{"class":463},[306,1055,601],{"class":467},[306,1057,500],{"class":463},[306,1059,1060],{"class":705},"403",[306,1062,574],{"class":463},[306,1064,1066,1068],{"class":308,"line":1065},44,[306,1067,894],{"class":459},[306,1069,1070],{"class":463}," { \n",[306,1072,1074,1077,1079,1081,1084,1086],{"class":308,"line":1073},45,[306,1075,1076],{"class":467},"      error",[306,1078,652],{"class":651},[306,1080,478],{"class":477},[306,1082,1083],{"class":481},"access_denied",[306,1085,485],{"class":477},[306,1087,1088],{"class":463},", \n",[306,1090,1092,1095,1097,1099,1102,1104],{"class":308,"line":1091},46,[306,1093,1094],{"class":467},"      message",[306,1096,652],{"class":651},[306,1098,478],{"class":477},[306,1100,1101],{"class":481},"Connections from the Tor network are not permitted.",[306,1103,485],{"class":477},[306,1105,1106],{"class":463}," \n",[306,1108,1110],{"class":308,"line":1109},47,[306,1111,1112],{"class":463},"    };\n",[306,1114,1116],{"class":308,"line":1115},48,[306,1117,737],{"class":463},[306,1119,1121],{"class":308,"line":1120},49,[306,1122,525],{"emptyLinePlaceholder":10},[306,1124,1126,1128,1130,1133],{"class":308,"line":1125},50,[306,1127,671],{"class":459},[306,1129,597],{"class":463},[306,1131,1132],{"class":467},"isDatacenter",[306,1134,682],{"class":463},[306,1136,1138],{"class":308,"line":1137},51,[306,1139,1140],{"class":530},"    \u002F\u002F Legitimate users do not log in from AWS servers. This is likely a script.\n",[306,1142,1144,1146,1148,1150,1152,1154],{"class":308,"line":1143},52,[306,1145,1051],{"class":552},[306,1147,556],{"class":463},[306,1149,601],{"class":467},[306,1151,500],{"class":463},[306,1153,1060],{"class":705},[306,1155,574],{"class":463},[306,1157,1159,1161],{"class":308,"line":1158},53,[306,1160,894],{"class":459},[306,1162,1070],{"class":463},[306,1164,1166,1168,1170,1172,1174,1176],{"class":308,"line":1165},54,[306,1167,1076],{"class":467},[306,1169,652],{"class":651},[306,1171,478],{"class":477},[306,1173,1083],{"class":481},[306,1175,485],{"class":477},[306,1177,1088],{"class":463},[306,1179,1181,1183,1185,1187,1190,1192],{"class":308,"line":1180},55,[306,1182,1094],{"class":467},[306,1184,652],{"class":651},[306,1186,478],{"class":477},[306,1188,1189],{"class":481},"Datacenter IP ranges are not permitted. Please disable your VPN.",[306,1191,485],{"class":477},[306,1193,1106],{"class":463},[306,1195,1197],{"class":308,"line":1196},56,[306,1198,1112],{"class":463},[306,1200,1202],{"class":308,"line":1201},57,[306,1203,737],{"class":463},[306,1205,1207],{"class":308,"line":1206},58,[306,1208,525],{"emptyLinePlaceholder":10},[306,1210,1212,1214,1216,1219],{"class":308,"line":1211},59,[306,1213,671],{"class":459},[306,1215,597],{"class":463},[306,1217,1218],{"class":467},"isHighRisk",[306,1220,682],{"class":463},[306,1222,1224],{"class":308,"line":1223},60,[306,1225,1226],{"class":530},"    \u002F\u002F The IP belongs to a residential proxy or commercial VPN. \n",[306,1228,1230],{"class":308,"line":1229},61,[306,1231,1232],{"class":530},"    \u002F\u002F It might be a malicious actor, or it might be a privacy-conscious user.\n",[306,1234,1236],{"class":308,"line":1235},62,[306,1237,1238],{"class":530},"    \u002F\u002F We do NOT block them outright. Instead, we introduce adaptive friction.\n",[306,1240,1242,1244,1246,1248,1250,1253],{"class":308,"line":1241},63,[306,1243,1051],{"class":552},[306,1245,556],{"class":463},[306,1247,601],{"class":467},[306,1249,500],{"class":463},[306,1251,1252],{"class":705},"401",[306,1254,574],{"class":463},[306,1256,1258,1260],{"class":308,"line":1257},64,[306,1259,894],{"class":459},[306,1261,1070],{"class":463},[306,1263,1265,1267,1269,1271,1274,1276],{"class":308,"line":1264},65,[306,1266,1076],{"class":467},[306,1268,652],{"class":651},[306,1270,478],{"class":477},[306,1272,1273],{"class":481},"verification_required",[306,1275,485],{"class":477},[306,1277,1088],{"class":463},[306,1279,1281,1284,1286,1288,1291,1293],{"class":308,"line":1280},66,[306,1282,1283],{"class":467},"      challengeType",[306,1285,652],{"class":651},[306,1287,478],{"class":477},[306,1289,1290],{"class":481},"mfa",[306,1292,485],{"class":477},[306,1294,709],{"class":463},[306,1296,1298,1300,1302,1304,1307,1309],{"class":308,"line":1297},67,[306,1299,1094],{"class":467},[306,1301,652],{"class":651},[306,1303,478],{"class":477},[306,1305,1306],{"class":481},"Unusual network detected. Please enter the code sent to your mobile device.",[306,1308,485],{"class":477},[306,1310,1106],{"class":463},[306,1312,1314],{"class":308,"line":1313},68,[306,1315,1112],{"class":463},[306,1317,1319],{"class":308,"line":1318},69,[306,1320,737],{"class":463},[306,1322,1324],{"class":308,"line":1323},70,[306,1325,665],{"class":463},[306,1327,1329],{"class":308,"line":1328},71,[306,1330,1331],{"class":530},"  \u002F\u002F 5. If all checks pass, proceed with standard authentication\n",[306,1333,1335,1337,1340,1342,1344,1346,1348,1350,1352,1354,1356,1358,1360,1362],{"class":308,"line":1334},72,[306,1336,630],{"class":536},[306,1338,1339],{"class":540}," authResult",[306,1341,545],{"class":544},[306,1343,755],{"class":459},[306,1345,897],{"class":552},[306,1347,556],{"class":463},[306,1349,902],{"class":467},[306,1351,562],{"class":463},[306,1353,907],{"class":467},[306,1355,500],{"class":463},[306,1357,902],{"class":467},[306,1359,562],{"class":463},[306,1361,916],{"class":467},[306,1363,574],{"class":463},[306,1365,1367],{"class":308,"line":1366},73,[306,1368,665],{"class":463},[306,1370,1372,1374,1376,1378,1381,1383,1386],{"class":308,"line":1371},74,[306,1373,671],{"class":459},[306,1375,597],{"class":463},[306,1377,676],{"class":544},[306,1379,1380],{"class":467},"authResult",[306,1382,562],{"class":463},[306,1384,1385],{"class":467},"success",[306,1387,682],{"class":463},[306,1389,1391],{"class":308,"line":1390},75,[306,1392,1393],{"class":530},"    \u002F\u002F Even if the IP is safe, standard credential checks still apply\n",[306,1395,1397,1399,1401],{"class":308,"line":1396},76,[306,1398,688],{"class":459},[306,1400,691],{"class":552},[306,1402,694],{"class":463},[306,1404,1406,1408,1410,1413],{"class":308,"line":1405},77,[306,1407,700],{"class":467},[306,1409,652],{"class":651},[306,1411,1412],{"class":705}," 401",[306,1414,709],{"class":463},[306,1416,1418,1420,1422,1424,1427],{"class":308,"line":1417},78,[306,1419,715],{"class":467},[306,1421,652],{"class":651},[306,1423,478],{"class":477},[306,1425,1426],{"class":481},"Invalid credentials",[306,1428,725],{"class":477},[306,1430,1432],{"class":308,"line":1431},79,[306,1433,731],{"class":463},[306,1435,1437],{"class":308,"line":1436},80,[306,1438,737],{"class":463},[306,1440,1442],{"class":308,"line":1441},81,[306,1443,525],{"emptyLinePlaceholder":10},[306,1445,1447,1450],{"class":308,"line":1446},82,[306,1448,1449],{"class":459},"  return",[306,1451,610],{"class":463},[306,1453,1455,1458,1460,1462],{"class":308,"line":1454},83,[306,1456,1457],{"class":467},"    success",[306,1459,652],{"class":651},[306,1461,656],{"class":655},[306,1463,709],{"class":463},[306,1465,1467,1470,1472,1474,1476,1479],{"class":308,"line":1466},84,[306,1468,1469],{"class":467},"    token",[306,1471,652],{"class":651},[306,1473,1339],{"class":467},[306,1475,562],{"class":463},[306,1477,1478],{"class":467},"token",[306,1480,709],{"class":463},[306,1482,1484,1487,1489,1491,1493],{"class":308,"line":1483},85,[306,1485,1486],{"class":467},"    user",[306,1488,652],{"class":651},[306,1490,1339],{"class":467},[306,1492,562],{"class":463},[306,1494,1495],{"class":467},"user\n",[306,1497,1499],{"class":308,"line":1498},86,[306,1500,1501],{"class":463},"  };\n",[306,1503,1505],{"class":308,"line":1504},87,[306,1506,1507],{"class":463},"});\n",[1509,1510,1511],"tip",{},[225,1512,1513,1514,1517],{},"Always test your IP extraction logic thoroughly. Misconfiguring the ",[303,1515,1516],{},"x-forwarded-for"," header parsing can lead to IP spoofing vulnerabilities, where an attacker injects a fake IP address to bypass your security checks.",[246,1519,1521],{"id":1520},"expressjs-implementation","Express.js Implementation",[225,1523,1524],{},"If your backend is built on traditional Express.js, the concepts remain identical, though the implementation syntax differs slightly. You implement this as a reusable middleware function that you attach to specific high-risk routes.",[296,1526,1531],{"className":1527,"code":1528,"filename":1529,"language":1530,"meta":301,"style":301},"language-javascript shiki shiki-themes light-plus light-plus dracula","const { IPShield } = require('@ip-shield\u002Fsdk');\nconst shield = new IPShield(process.env.IP_SHIELD_API_KEY);\n\n\u002F**\n * Express middleware to evaluate IP risk before processing requests\n *\u002F\nasync function ipIntelligenceMiddleware(req, res, next) {\n  \u002F\u002F Extract IP, respecting trust proxy settings in Express\n  const ip = req.ip;\n\n  try {\n    const networkData = await shield.network.lookup(ip);\n    \n    \u002F\u002F Attach the intelligence data to the request object for downstream use\n    req.ipIntelligence = networkData;\n\n    \u002F\u002F Hard block for Tor and Datacenters\n    if (networkData.isTor || networkData.asn.type === 'hosting') {\n      return res.status(403).json({\n        error: 'Forbidden',\n        message: 'Your network type is not permitted to access this resource.'\n      });\n    }\n\n    \u002F\u002F Flag for downstream adaptive friction\n    if (networkData.isProxy || networkData.isVpn) {\n      req.requiresMfa = true;\n    }\n\n    next();\n  } catch (error) {\n    console.error('IP Shield API Error:', error);\n    \u002F\u002F Fail open to prevent locking out legitimate users during an outage\n    next();\n  }\n}\n\nmodule.exports = ipIntelligenceMiddleware;\n","middleware\u002FipIntelligence.js","javascript",[303,1532,1533,1559,1585,1589,1594,1599,1604,1631,1636,1653,1657,1663,1690,1694,1699,1715,1719,1724,1759,1783,1799,1813,1818,1823,1827,1832,1854,1870,1874,1878,1886,1898,1921,1926,1932,1936,1941,1945],{"__ignoreMap":301},[306,1534,1535,1537,1539,1541,1543,1546,1549,1551,1553,1555,1557],{"class":308,"line":309},[306,1536,537],{"class":536},[306,1538,464],{"class":463},[306,1540,468],{"class":540},[306,1542,471],{"class":463},[306,1544,1545],{"class":544},"=",[306,1547,1548],{"class":552}," require",[306,1550,556],{"class":463},[306,1552,485],{"class":477},[306,1554,482],{"class":481},[306,1556,485],{"class":477},[306,1558,574],{"class":463},[306,1560,1561,1563,1565,1567,1569,1571,1573,1575,1577,1579,1581,1583],{"class":308,"line":315},[306,1562,537],{"class":536},[306,1564,541],{"class":540},[306,1566,545],{"class":544},[306,1568,549],{"class":548},[306,1570,553],{"class":552},[306,1572,556],{"class":463},[306,1574,559],{"class":467},[306,1576,562],{"class":463},[306,1578,565],{"class":467},[306,1580,562],{"class":463},[306,1582,571],{"class":570},[306,1584,574],{"class":463},[306,1586,1587],{"class":308,"line":321},[306,1588,525],{"emptyLinePlaceholder":10},[306,1590,1591],{"class":308,"line":327},[306,1592,1593],{"class":530},"\u002F**\n",[306,1595,1596],{"class":308,"line":333},[306,1597,1598],{"class":530}," * Express middleware to evaluate IP risk before processing requests\n",[306,1600,1601],{"class":308,"line":339},[306,1602,1603],{"class":530}," *\u002F\n",[306,1605,1606,1608,1611,1614,1616,1619,1621,1624,1626,1629],{"class":308,"line":345},[306,1607,594],{"class":536},[306,1609,1610],{"class":536}," function",[306,1612,1613],{"class":552}," ipIntelligenceMiddleware",[306,1615,556],{"class":463},[306,1617,1618],{"class":600},"req",[306,1620,500],{"class":463},[306,1622,1623],{"class":600},"res",[306,1625,500],{"class":463},[306,1627,1628],{"class":600},"next",[306,1630,682],{"class":463},[306,1632,1633],{"class":308,"line":351},[306,1634,1635],{"class":530},"  \u002F\u002F Extract IP, respecting trust proxy settings in Express\n",[306,1637,1638,1640,1642,1644,1647,1649,1651],{"class":308,"line":357},[306,1639,630],{"class":536},[306,1641,633],{"class":540},[306,1643,545],{"class":544},[306,1645,1646],{"class":467}," req",[306,1648,562],{"class":463},[306,1650,679],{"class":467},[306,1652,488],{"class":463},[306,1654,1655],{"class":308,"line":363},[306,1656,525],{"emptyLinePlaceholder":10},[306,1658,1659,1661],{"class":308,"line":369},[306,1660,810],{"class":459},[306,1662,610],{"class":463},[306,1664,1665,1668,1670,1672,1674,1676,1678,1680,1682,1684,1686,1688],{"class":308,"line":662},[306,1666,1667],{"class":536},"    const",[306,1669,802],{"class":540},[306,1671,545],{"class":544},[306,1673,755],{"class":459},[306,1675,541],{"class":467},[306,1677,562],{"class":463},[306,1679,829],{"class":467},[306,1681,562],{"class":463},[306,1683,834],{"class":552},[306,1685,556],{"class":463},[306,1687,679],{"class":467},[306,1689,574],{"class":463},[306,1691,1692],{"class":308,"line":668},[306,1693,360],{"class":463},[306,1695,1696],{"class":308,"line":685},[306,1697,1698],{"class":530},"    \u002F\u002F Attach the intelligence data to the request object for downstream use\n",[306,1700,1701,1704,1706,1709,1711,1713],{"class":308,"line":697},[306,1702,1703],{"class":467},"    req",[306,1705,562],{"class":463},[306,1707,1708],{"class":467},"ipIntelligence",[306,1710,545],{"class":544},[306,1712,802],{"class":467},[306,1714,488],{"class":463},[306,1716,1717],{"class":308,"line":712},[306,1718,525],{"emptyLinePlaceholder":10},[306,1720,1721],{"class":308,"line":728},[306,1722,1723],{"class":530},"    \u002F\u002F Hard block for Tor and Datacenters\n",[306,1725,1726,1729,1731,1733,1735,1737,1739,1741,1743,1745,1747,1749,1751,1753,1755,1757],{"class":308,"line":734},[306,1727,1728],{"class":459},"    if",[306,1730,597],{"class":463},[306,1732,1027],{"class":467},[306,1734,562],{"class":463},[306,1736,970],{"class":467},[306,1738,954],{"class":544},[306,1740,802],{"class":467},[306,1742,562],{"class":463},[306,1744,989],{"class":467},[306,1746,562],{"class":463},[306,1748,994],{"class":467},[306,1750,997],{"class":544},[306,1752,478],{"class":477},[306,1754,1002],{"class":481},[306,1756,485],{"class":477},[306,1758,682],{"class":463},[306,1760,1761,1764,1767,1769,1772,1774,1776,1779,1781],{"class":308,"line":740},[306,1762,1763],{"class":459},"      return",[306,1765,1766],{"class":467}," res",[306,1768,562],{"class":463},[306,1770,1771],{"class":552},"status",[306,1773,556],{"class":463},[306,1775,1060],{"class":705},[306,1777,1778],{"class":463},").",[306,1780,5],{"class":552},[306,1782,694],{"class":463},[306,1784,1785,1788,1790,1792,1795,1797],{"class":308,"line":745},[306,1786,1787],{"class":467},"        error",[306,1789,652],{"class":651},[306,1791,478],{"class":477},[306,1793,1794],{"class":481},"Forbidden",[306,1796,485],{"class":477},[306,1798,709],{"class":463},[306,1800,1801,1804,1806,1808,1811],{"class":308,"line":767},[306,1802,1803],{"class":467},"        message",[306,1805,652],{"class":651},[306,1807,478],{"class":477},[306,1809,1810],{"class":481},"Your network type is not permitted to access this resource.",[306,1812,725],{"class":477},[306,1814,1815],{"class":308,"line":772},[306,1816,1817],{"class":463},"      });\n",[306,1819,1820],{"class":308,"line":778},[306,1821,1822],{"class":463},"    }\n",[306,1824,1825],{"class":308,"line":784},[306,1826,525],{"emptyLinePlaceholder":10},[306,1828,1829],{"class":308,"line":790},[306,1830,1831],{"class":530},"    \u002F\u002F Flag for downstream adaptive friction\n",[306,1833,1834,1836,1838,1840,1842,1844,1846,1848,1850,1852],{"class":308,"line":796},[306,1835,1728],{"class":459},[306,1837,597],{"class":463},[306,1839,1027],{"class":467},[306,1841,562],{"class":463},[306,1843,951],{"class":467},[306,1845,954],{"class":544},[306,1847,802],{"class":467},[306,1849,562],{"class":463},[306,1851,961],{"class":467},[306,1853,682],{"class":463},[306,1855,1856,1859,1861,1864,1866,1868],{"class":308,"line":807},[306,1857,1858],{"class":467},"      req",[306,1860,562],{"class":463},[306,1862,1863],{"class":467},"requiresMfa",[306,1865,545],{"class":544},[306,1867,656],{"class":655},[306,1869,488],{"class":463},[306,1871,1872],{"class":308,"line":815},[306,1873,1822],{"class":463},[306,1875,1876],{"class":308,"line":843},[306,1877,525],{"emptyLinePlaceholder":10},[306,1879,1880,1883],{"class":308,"line":859},[306,1881,1882],{"class":552},"    next",[306,1884,1885],{"class":463},"();\n",[306,1887,1888,1890,1892,1894,1896],{"class":308,"line":885},[306,1889,846],{"class":463},[306,1891,849],{"class":459},[306,1893,597],{"class":463},[306,1895,867],{"class":467},[306,1897,682],{"class":463},[306,1899,1900,1902,1904,1906,1908,1910,1913,1915,1917,1919],{"class":308,"line":891},[306,1901,862],{"class":467},[306,1903,562],{"class":463},[306,1905,867],{"class":552},[306,1907,556],{"class":463},[306,1909,485],{"class":477},[306,1911,1912],{"class":481},"IP Shield API Error:",[306,1914,485],{"class":477},[306,1916,500],{"class":463},[306,1918,867],{"class":467},[306,1920,574],{"class":463},[306,1922,1923],{"class":308,"line":921},[306,1924,1925],{"class":530},"    \u002F\u002F Fail open to prevent locking out legitimate users during an outage\n",[306,1927,1928,1930],{"class":308,"line":926},[306,1929,1882],{"class":552},[306,1931,1885],{"class":463},[306,1933,1934],{"class":308,"line":931},[306,1935,737],{"class":463},[306,1937,1938],{"class":308,"line":937},[306,1939,1940],{"class":463},"}\n",[306,1942,1943],{"class":308,"line":975},[306,1944,525],{"emptyLinePlaceholder":10},[306,1946,1947,1951,1953,1956,1958,1960],{"class":308,"line":1009},[306,1948,1950],{"class":1949},"sFs1U","module",[306,1952,562],{"class":463},[306,1954,1955],{"class":1949},"exports",[306,1957,545],{"class":544},[306,1959,1613],{"class":467},[306,1961,488],{"class":463},[225,1963,1964],{},"You then apply this middleware to your sensitive routes:",[296,1966,1969],{"className":1527,"code":1967,"filename":1968,"language":1530,"meta":301,"style":301},"const express = require('express');\nconst router = express.Router();\nconst ipIntelligence = require('..\u002Fmiddleware\u002FipIntelligence');\n\n\u002F\u002F Apply the IP intelligence middleware specifically to the login route\nrouter.post('\u002Flogin', ipIntelligence, async (req, res) => {\n  const { email, password } = req.body;\n\n  \u002F\u002F Check if the middleware flagged this request for MFA\n  if (req.requiresMfa) {\n    return res.status(401).json({\n      error: 'MFA_REQUIRED',\n      message: 'Please complete multi-factor authentication.'\n    });\n  }\n\n  \u002F\u002F Standard login logic...\n  res.json({ success: true });\n});\n\nmodule.exports = router;\n","routes\u002Fauth.js",[303,1970,1971,1993,2011,2033,2037,2042,2083,2107,2111,2116,2130,2150,2165,2178,2182,2186,2190,2195,2215,2219,2223],{"__ignoreMap":301},[306,1972,1973,1975,1978,1980,1982,1984,1986,1989,1991],{"class":308,"line":309},[306,1974,537],{"class":536},[306,1976,1977],{"class":540}," express",[306,1979,545],{"class":544},[306,1981,1548],{"class":552},[306,1983,556],{"class":463},[306,1985,485],{"class":477},[306,1987,1988],{"class":481},"express",[306,1990,485],{"class":477},[306,1992,574],{"class":463},[306,1994,1995,1997,2000,2002,2004,2006,2009],{"class":308,"line":315},[306,1996,537],{"class":536},[306,1998,1999],{"class":540}," router",[306,2001,545],{"class":544},[306,2003,1977],{"class":467},[306,2005,562],{"class":463},[306,2007,2008],{"class":552},"Router",[306,2010,1885],{"class":463},[306,2012,2013,2015,2018,2020,2022,2024,2026,2029,2031],{"class":308,"line":321},[306,2014,537],{"class":536},[306,2016,2017],{"class":540}," ipIntelligence",[306,2019,545],{"class":544},[306,2021,1548],{"class":552},[306,2023,556],{"class":463},[306,2025,485],{"class":477},[306,2027,2028],{"class":481},"..\u002Fmiddleware\u002FipIntelligence",[306,2030,485],{"class":477},[306,2032,574],{"class":463},[306,2034,2035],{"class":308,"line":327},[306,2036,525],{"emptyLinePlaceholder":10},[306,2038,2039],{"class":308,"line":333},[306,2040,2041],{"class":530},"\u002F\u002F Apply the IP intelligence middleware specifically to the login route\n",[306,2043,2044,2047,2049,2052,2054,2056,2059,2061,2063,2065,2067,2069,2071,2073,2075,2077,2079,2081],{"class":308,"line":339},[306,2045,2046],{"class":467},"router",[306,2048,562],{"class":463},[306,2050,2051],{"class":552},"post",[306,2053,556],{"class":463},[306,2055,485],{"class":477},[306,2057,2058],{"class":481},"\u002Flogin",[306,2060,485],{"class":477},[306,2062,500],{"class":463},[306,2064,1708],{"class":467},[306,2066,500],{"class":463},[306,2068,594],{"class":536},[306,2070,597],{"class":463},[306,2072,1618],{"class":600},[306,2074,500],{"class":463},[306,2076,1623],{"class":600},[306,2078,604],{"class":463},[306,2080,607],{"class":536},[306,2082,610],{"class":463},[306,2084,2085,2087,2089,2091,2093,2095,2097,2099,2101,2103,2105],{"class":308,"line":345},[306,2086,630],{"class":536},[306,2088,464],{"class":463},[306,2090,907],{"class":540},[306,2092,500],{"class":463},[306,2094,916],{"class":540},[306,2096,471],{"class":463},[306,2098,1545],{"class":544},[306,2100,1646],{"class":467},[306,2102,562],{"class":463},[306,2104,902],{"class":467},[306,2106,488],{"class":463},[306,2108,2109],{"class":308,"line":351},[306,2110,525],{"emptyLinePlaceholder":10},[306,2112,2113],{"class":308,"line":357},[306,2114,2115],{"class":530},"  \u002F\u002F Check if the middleware flagged this request for MFA\n",[306,2117,2118,2120,2122,2124,2126,2128],{"class":308,"line":363},[306,2119,671],{"class":459},[306,2121,597],{"class":463},[306,2123,1618],{"class":467},[306,2125,562],{"class":463},[306,2127,1863],{"class":467},[306,2129,682],{"class":463},[306,2131,2132,2134,2136,2138,2140,2142,2144,2146,2148],{"class":308,"line":369},[306,2133,894],{"class":459},[306,2135,1766],{"class":467},[306,2137,562],{"class":463},[306,2139,1771],{"class":552},[306,2141,556],{"class":463},[306,2143,1252],{"class":705},[306,2145,1778],{"class":463},[306,2147,5],{"class":552},[306,2149,694],{"class":463},[306,2151,2152,2154,2156,2158,2161,2163],{"class":308,"line":662},[306,2153,1076],{"class":467},[306,2155,652],{"class":651},[306,2157,478],{"class":477},[306,2159,2160],{"class":481},"MFA_REQUIRED",[306,2162,485],{"class":477},[306,2164,709],{"class":463},[306,2166,2167,2169,2171,2173,2176],{"class":308,"line":668},[306,2168,1094],{"class":467},[306,2170,652],{"class":651},[306,2172,478],{"class":477},[306,2174,2175],{"class":481},"Please complete multi-factor authentication.",[306,2177,725],{"class":477},[306,2179,2180],{"class":308,"line":685},[306,2181,731],{"class":463},[306,2183,2184],{"class":308,"line":697},[306,2185,737],{"class":463},[306,2187,2188],{"class":308,"line":712},[306,2189,525],{"emptyLinePlaceholder":10},[306,2191,2192],{"class":308,"line":728},[306,2193,2194],{"class":530},"  \u002F\u002F Standard login logic...\n",[306,2196,2197,2200,2202,2204,2207,2209,2211,2213],{"class":308,"line":734},[306,2198,2199],{"class":467},"  res",[306,2201,562],{"class":463},[306,2203,5],{"class":552},[306,2205,2206],{"class":463},"({ ",[306,2208,1385],{"class":467},[306,2210,652],{"class":651},[306,2212,656],{"class":655},[306,2214,659],{"class":463},[306,2216,2217],{"class":308,"line":740},[306,2218,1507],{"class":463},[306,2220,2221],{"class":308,"line":745},[306,2222,525],{"emptyLinePlaceholder":10},[306,2224,2225,2227,2229,2231,2233,2235],{"class":308,"line":767},[306,2226,1950],{"class":1949},[306,2228,562],{"class":463},[306,2230,1955],{"class":1949},[306,2232,545],{"class":544},[306,2234,1999],{"class":467},[306,2236,488],{"class":463},[246,2238,2240],{"id":2239},"implementing-at-the-edge-with-cloudflare-workers","Implementing at the Edge with Cloudflare Workers",[225,2242,2243],{},"For maximum performance, you move your security logic as close to the user as possible. Cloudflare Workers allow you to intercept requests at the CDN edge, before they ever reach your origin server. This protects your backend infrastructure from the computational load of processing malicious requests.",[296,2245,2248],{"className":1527,"code":2246,"filename":2247,"language":1530,"meta":301,"style":301},"export default {\n  async fetch(request, env, ctx) {\n    const url = new URL(request.url);\n    \n    \u002F\u002F Only run the heavy IP check on sensitive endpoints to save costs and latency\n    if (url.pathname !== '\u002Fapi\u002Fv1\u002Flogin' && url.pathname !== '\u002Fapi\u002Fv1\u002Fcheckout') {\n      return fetch(request);\n    }\n\n    \u002F\u002F Cloudflare provides the client IP in the headers\n    const clientIP = request.headers.get('CF-Connecting-IP');\n\n    try {\n      \u002F\u002F Make a subrequest to the IP Shield API\n      const shieldResponse = await fetch(`https:\u002F\u002Fip-shield.riavzon.com\u002Fv1\u002Fnetwork\u002F${clientIP}`, {\n        headers: {\n          'Authorization': `Bearer ${env.IP_SHIELD_API_KEY}`\n        }\n      });\n\n      if (shieldResponse.ok) {\n        const networkData = await shieldResponse.json();\n\n        \u002F\u002F Implement blocking logic at the edge\n        if (networkData.isTor || networkData.asn.type === 'hosting') {\n          return new Response(JSON.stringify({ error: 'Access Denied' }), {\n            status: 403,\n            headers: { 'Content-Type': 'application\u002Fjson' }\n          });\n        }\n        \n        \u002F\u002F Pass intelligence data to the origin server via custom headers\n        const modifiedRequest = new Request(request);\n        if (networkData.isProxy || networkData.isVpn) {\n          modifiedRequest.headers.set('X-Requires-Adaptive-Friction', 'true');\n        }\n        \n        return fetch(modifiedRequest);\n      }\n    } catch (err) {\n      \u002F\u002F Fail open on error\n      console.error('Edge security check failed:', err);\n    }\n\n    return fetch(request);\n  }\n};\n","worker.js",[303,2249,2250,2258,2282,2307,2311,2316,2359,2371,2375,2379,2384,2417,2421,2428,2433,2467,2476,2505,2510,2514,2518,2535,2554,2558,2563,2598,2634,2646,2674,2679,2683,2688,2693,2713,2735,2769,2773,2777,2791,2796,2809,2814,2838,2842,2846,2858,2862],{"__ignoreMap":301},[306,2251,2252,2254,2256],{"class":308,"line":309},[306,2253,583],{"class":459},[306,2255,586],{"class":459},[306,2257,610],{"class":463},[306,2259,2260,2263,2266,2268,2271,2273,2275,2277,2280],{"class":308,"line":315},[306,2261,2262],{"class":536},"  async",[306,2264,2265],{"class":552}," fetch",[306,2267,556],{"class":463},[306,2269,2270],{"class":600},"request",[306,2272,500],{"class":463},[306,2274,565],{"class":600},[306,2276,500],{"class":463},[306,2278,2279],{"class":600},"ctx",[306,2281,682],{"class":463},[306,2283,2284,2286,2289,2291,2293,2296,2298,2300,2302,2305],{"class":308,"line":321},[306,2285,1667],{"class":536},[306,2287,2288],{"class":540}," url",[306,2290,545],{"class":544},[306,2292,549],{"class":548},[306,2294,2295],{"class":552}," URL",[306,2297,556],{"class":463},[306,2299,2270],{"class":467},[306,2301,562],{"class":463},[306,2303,2304],{"class":467},"url",[306,2306,574],{"class":463},[306,2308,2309],{"class":308,"line":327},[306,2310,360],{"class":463},[306,2312,2313],{"class":308,"line":333},[306,2314,2315],{"class":530},"    \u002F\u002F Only run the heavy IP check on sensitive endpoints to save costs and latency\n",[306,2317,2318,2320,2322,2324,2326,2329,2332,2334,2337,2339,2342,2344,2346,2348,2350,2352,2355,2357],{"class":308,"line":339},[306,2319,1728],{"class":459},[306,2321,597],{"class":463},[306,2323,2304],{"class":467},[306,2325,562],{"class":463},[306,2327,2328],{"class":467},"pathname",[306,2330,2331],{"class":544}," !==",[306,2333,478],{"class":477},[306,2335,2336],{"class":481},"\u002Fapi\u002Fv1\u002Flogin",[306,2338,485],{"class":477},[306,2340,2341],{"class":544}," &&",[306,2343,2288],{"class":467},[306,2345,562],{"class":463},[306,2347,2328],{"class":467},[306,2349,2331],{"class":544},[306,2351,478],{"class":477},[306,2353,2354],{"class":481},"\u002Fapi\u002Fv1\u002Fcheckout",[306,2356,485],{"class":477},[306,2358,682],{"class":463},[306,2360,2361,2363,2365,2367,2369],{"class":308,"line":345},[306,2362,1763],{"class":459},[306,2364,2265],{"class":552},[306,2366,556],{"class":463},[306,2368,2270],{"class":467},[306,2370,574],{"class":463},[306,2372,2373],{"class":308,"line":351},[306,2374,1822],{"class":463},[306,2376,2377],{"class":308,"line":357},[306,2378,525],{"emptyLinePlaceholder":10},[306,2380,2381],{"class":308,"line":363},[306,2382,2383],{"class":530},"    \u002F\u002F Cloudflare provides the client IP in the headers\n",[306,2385,2386,2388,2391,2393,2396,2398,2401,2403,2406,2408,2410,2413,2415],{"class":308,"line":369},[306,2387,1667],{"class":536},[306,2389,2390],{"class":540}," clientIP",[306,2392,545],{"class":544},[306,2394,2395],{"class":467}," request",[306,2397,562],{"class":463},[306,2399,2400],{"class":467},"headers",[306,2402,562],{"class":463},[306,2404,2405],{"class":552},"get",[306,2407,556],{"class":463},[306,2409,485],{"class":477},[306,2411,2412],{"class":481},"CF-Connecting-IP",[306,2414,485],{"class":477},[306,2416,574],{"class":463},[306,2418,2419],{"class":308,"line":662},[306,2420,525],{"emptyLinePlaceholder":10},[306,2422,2423,2426],{"class":308,"line":668},[306,2424,2425],{"class":459},"    try",[306,2427,610],{"class":463},[306,2429,2430],{"class":308,"line":685},[306,2431,2432],{"class":530},"      \u002F\u002F Make a subrequest to the IP Shield API\n",[306,2434,2435,2438,2441,2443,2445,2447,2449,2452,2455,2458,2461,2464],{"class":308,"line":697},[306,2436,2437],{"class":536},"      const",[306,2439,2440],{"class":540}," shieldResponse",[306,2442,545],{"class":544},[306,2444,755],{"class":459},[306,2446,2265],{"class":552},[306,2448,556],{"class":463},[306,2450,2451],{"class":481},"`https:\u002F\u002Fip-shield.riavzon.com\u002Fv1\u002Fnetwork\u002F",[306,2453,2454],{"class":536},"${",[306,2456,2457],{"class":467},"clientIP",[306,2459,2460],{"class":536},"}",[306,2462,2463],{"class":481},"`",[306,2465,2466],{"class":463},", {\n",[306,2468,2469,2472,2474],{"class":308,"line":712},[306,2470,2471],{"class":467},"        headers",[306,2473,652],{"class":651},[306,2475,610],{"class":463},[306,2477,2478,2481,2484,2486,2488,2491,2493,2495,2498,2500,2502],{"class":308,"line":728},[306,2479,2480],{"class":477},"          '",[306,2482,2483],{"class":481},"Authorization",[306,2485,485],{"class":477},[306,2487,652],{"class":651},[306,2489,2490],{"class":481}," `Bearer ",[306,2492,2454],{"class":536},[306,2494,565],{"class":467},[306,2496,562],{"class":2497},"s1lnM",[306,2499,571],{"class":570},[306,2501,2460],{"class":536},[306,2503,2504],{"class":481},"`\n",[306,2506,2507],{"class":308,"line":734},[306,2508,2509],{"class":463},"        }\n",[306,2511,2512],{"class":308,"line":740},[306,2513,1817],{"class":463},[306,2515,2516],{"class":308,"line":745},[306,2517,525],{"emptyLinePlaceholder":10},[306,2519,2520,2523,2525,2528,2530,2533],{"class":308,"line":767},[306,2521,2522],{"class":459},"      if",[306,2524,597],{"class":463},[306,2526,2527],{"class":467},"shieldResponse",[306,2529,562],{"class":463},[306,2531,2532],{"class":467},"ok",[306,2534,682],{"class":463},[306,2536,2537,2540,2542,2544,2546,2548,2550,2552],{"class":308,"line":772},[306,2538,2539],{"class":536},"        const",[306,2541,802],{"class":540},[306,2543,545],{"class":544},[306,2545,755],{"class":459},[306,2547,2440],{"class":467},[306,2549,562],{"class":463},[306,2551,5],{"class":552},[306,2553,1885],{"class":463},[306,2555,2556],{"class":308,"line":778},[306,2557,525],{"emptyLinePlaceholder":10},[306,2559,2560],{"class":308,"line":784},[306,2561,2562],{"class":530},"        \u002F\u002F Implement blocking logic at the edge\n",[306,2564,2565,2568,2570,2572,2574,2576,2578,2580,2582,2584,2586,2588,2590,2592,2594,2596],{"class":308,"line":790},[306,2566,2567],{"class":459},"        if",[306,2569,597],{"class":463},[306,2571,1027],{"class":467},[306,2573,562],{"class":463},[306,2575,970],{"class":467},[306,2577,954],{"class":544},[306,2579,802],{"class":467},[306,2581,562],{"class":463},[306,2583,989],{"class":467},[306,2585,562],{"class":463},[306,2587,994],{"class":467},[306,2589,997],{"class":544},[306,2591,478],{"class":477},[306,2593,1002],{"class":481},[306,2595,485],{"class":477},[306,2597,682],{"class":463},[306,2599,2600,2603,2605,2608,2610,2613,2615,2618,2620,2622,2624,2626,2629,2631],{"class":308,"line":796},[306,2601,2602],{"class":459},"          return",[306,2604,549],{"class":548},[306,2606,2607],{"class":552}," Response",[306,2609,556],{"class":463},[306,2611,2612],{"class":570},"JSON",[306,2614,562],{"class":463},[306,2616,2617],{"class":552},"stringify",[306,2619,2206],{"class":463},[306,2621,867],{"class":467},[306,2623,652],{"class":651},[306,2625,478],{"class":477},[306,2627,2628],{"class":481},"Access Denied",[306,2630,485],{"class":477},[306,2632,2633],{"class":463}," }), {\n",[306,2635,2636,2639,2641,2644],{"class":308,"line":807},[306,2637,2638],{"class":467},"            status",[306,2640,652],{"class":651},[306,2642,2643],{"class":705}," 403",[306,2645,709],{"class":463},[306,2647,2648,2651,2653,2655,2657,2660,2662,2664,2666,2669,2671],{"class":308,"line":815},[306,2649,2650],{"class":467},"            headers",[306,2652,652],{"class":651},[306,2654,464],{"class":463},[306,2656,485],{"class":477},[306,2658,2659],{"class":481},"Content-Type",[306,2661,485],{"class":477},[306,2663,652],{"class":651},[306,2665,478],{"class":477},[306,2667,2668],{"class":481},"application\u002Fjson",[306,2670,485],{"class":477},[306,2672,2673],{"class":463}," }\n",[306,2675,2676],{"class":308,"line":843},[306,2677,2678],{"class":463},"          });\n",[306,2680,2681],{"class":308,"line":859},[306,2682,2509],{"class":463},[306,2684,2685],{"class":308,"line":885},[306,2686,2687],{"class":463},"        \n",[306,2689,2690],{"class":308,"line":891},[306,2691,2692],{"class":530},"        \u002F\u002F Pass intelligence data to the origin server via custom headers\n",[306,2694,2695,2697,2700,2702,2704,2707,2709,2711],{"class":308,"line":921},[306,2696,2539],{"class":536},[306,2698,2699],{"class":540}," modifiedRequest",[306,2701,545],{"class":544},[306,2703,549],{"class":548},[306,2705,2706],{"class":552}," Request",[306,2708,556],{"class":463},[306,2710,2270],{"class":467},[306,2712,574],{"class":463},[306,2714,2715,2717,2719,2721,2723,2725,2727,2729,2731,2733],{"class":308,"line":926},[306,2716,2567],{"class":459},[306,2718,597],{"class":463},[306,2720,1027],{"class":467},[306,2722,562],{"class":463},[306,2724,951],{"class":467},[306,2726,954],{"class":544},[306,2728,802],{"class":467},[306,2730,562],{"class":463},[306,2732,961],{"class":467},[306,2734,682],{"class":463},[306,2736,2737,2740,2742,2744,2746,2749,2751,2753,2756,2758,2760,2762,2765,2767],{"class":308,"line":931},[306,2738,2739],{"class":467},"          modifiedRequest",[306,2741,562],{"class":463},[306,2743,2400],{"class":467},[306,2745,562],{"class":463},[306,2747,2748],{"class":552},"set",[306,2750,556],{"class":463},[306,2752,485],{"class":477},[306,2754,2755],{"class":481},"X-Requires-Adaptive-Friction",[306,2757,485],{"class":477},[306,2759,500],{"class":463},[306,2761,485],{"class":477},[306,2763,2764],{"class":481},"true",[306,2766,485],{"class":477},[306,2768,574],{"class":463},[306,2770,2771],{"class":308,"line":937},[306,2772,2509],{"class":463},[306,2774,2775],{"class":308,"line":975},[306,2776,2687],{"class":463},[306,2778,2779,2782,2784,2786,2789],{"class":308,"line":1009},[306,2780,2781],{"class":459},"        return",[306,2783,2265],{"class":552},[306,2785,556],{"class":463},[306,2787,2788],{"class":467},"modifiedRequest",[306,2790,574],{"class":463},[306,2792,2793],{"class":308,"line":1014},[306,2794,2795],{"class":463},"      }\n",[306,2797,2798,2801,2803,2805,2807],{"class":308,"line":1020},[306,2799,2800],{"class":463},"    } ",[306,2802,849],{"class":459},[306,2804,597],{"class":463},[306,2806,854],{"class":467},[306,2808,682],{"class":463},[306,2810,2811],{"class":308,"line":1036},[306,2812,2813],{"class":530},"      \u002F\u002F Fail open on error\n",[306,2815,2816,2819,2821,2823,2825,2827,2830,2832,2834,2836],{"class":308,"line":1042},[306,2817,2818],{"class":467},"      console",[306,2820,562],{"class":463},[306,2822,867],{"class":552},[306,2824,556],{"class":463},[306,2826,485],{"class":477},[306,2828,2829],{"class":481},"Edge security check failed:",[306,2831,485],{"class":477},[306,2833,500],{"class":463},[306,2835,854],{"class":467},[306,2837,574],{"class":463},[306,2839,2840],{"class":308,"line":1048},[306,2841,1822],{"class":463},[306,2843,2844],{"class":308,"line":1065},[306,2845,525],{"emptyLinePlaceholder":10},[306,2847,2848,2850,2852,2854,2856],{"class":308,"line":1073},[306,2849,894],{"class":459},[306,2851,2265],{"class":552},[306,2853,556],{"class":463},[306,2855,2270],{"class":467},[306,2857,574],{"class":463},[306,2859,2860],{"class":308,"line":1091},[306,2861,737],{"class":463},[306,2863,2864],{"class":308,"line":1109},[306,2865,2866],{"class":463},"};\n",[2868,2869,2870],"important",{},[225,2871,2872],{},"When implementing edge security, always ensure your origin server is configured to ONLY accept traffic from your Edge provider (e.g., Cloudflare IP ranges). Otherwise, attackers simply bypass the edge worker by connecting to your origin IP directly.",[238,2874,2876],{"id":2875},"the-challenge-of-ipv6-and-subnet-hopping","The Challenge of IPv6 and Subnet Hopping",[225,2878,2879,2880,2883],{},"As the internet transitions to IPv6, attackers gain access to an unimaginably large address space. Traditional IPv4 blocklists fail against IPv6 because an attacker can cycle through billions of IP addresses within a single ",[303,2881,2882],{},"\u002F64"," subnet.",[225,2885,2886,2887,2890,2891,2893],{},"When dealing with IPv6, you must adjust your defensive strategies. You no longer block or evaluate individual ",[303,2888,2889],{},"\u002F128"," IP addresses. Instead, you apply your logic to the entire ",[303,2892,2882],{}," subnet. IP Shield handles this complexity automatically, aggregating intelligence across IPv6 blocks so that if an attacker hops IPs within their assigned subnet, the threat score remains accurate.",[246,2895,2897],{"id":2896},"subnet-aggregation-strategies","Subnet Aggregation Strategies",[254,2899,2900,2914],{},[257,2901,2902,2905,2906,2909,2910,2913],{},[260,2903,2904],{},"IPv4",": Track and evaluate on a ",[303,2907,2908],{},"\u002F32"," (individual IP) or ",[303,2911,2912],{},"\u002F24"," (C-class subnet) basis.",[257,2915,2916,2919,2920,2922],{},[260,2917,2918],{},"IPv6",": Always track and evaluate on a minimum of a ",[303,2921,2882],{}," basis.",[225,2924,2925,2926,2929,2930,2933],{},"If you observe malicious activity from ",[303,2927,2928],{},"2001:db8:1234:5678:90ab:cdef:0123:4567",", you should apply security friction to the entire ",[303,2931,2932],{},"2001:db8:1234:5678::\u002F64"," range.",[238,2935,2937],{"id":2936},"advanced-techniques-correlating-signals","Advanced Techniques: Correlating Signals",[225,2939,2940],{},"IP intelligence is incredibly powerful, but it becomes exponentially more effective when combined with other security signals. To build a truly resilient system against advanced residential proxies, you must correlate network data with client-side telemetry.",[246,2942,2944],{"id":2943},"device-fingerprinting","Device Fingerprinting",[225,2946,2947],{},"Attackers using residential proxies often route traffic from hundreds of IPs, but they might use the same underlying hardware or scraping script for all requests. By implementing device fingerprinting—analyzing the Canvas API rendering, WebGL drivers, audio context, and font stacks—you generate a unique identifier for the machine making the request.",[225,2949,2950],{},"If you observe 500 different residential IPs logging into 500 different accounts, but all 500 requests share the exact same highly unique device fingerprint, you definitively identify an ongoing attack.",[246,2952,2954],{"id":2953},"behavioral-biometrics","Behavioral Biometrics",[225,2956,2957],{},"How does the user interact with the page? Does the mouse move in perfectly straight lines? Are keystrokes registering with zero variance in timing? Human behavior is messy and unpredictable. Scrapers and bots, even those using residential proxies, often exhibit robotic perfection.",[225,2959,2960],{},"By combining IP Shield's network data with behavioral biometrics, you achieve unprecedented detection accuracy.",[238,2962,2964],{"id":2963},"creating-a-splunk-dashboard-for-traffic-analysis","Creating a Splunk Dashboard for Traffic Analysis",[225,2966,2967],{},"Monitoring your traffic is just as important as blocking it. By logging the IP Shield metadata alongside your standard access logs, you create powerful visualizations in tools like Splunk, ELK (Elasticsearch, Logstash, Kibana), or Datadog.",[225,2969,2970],{},"Here is an example Splunk SPL query to identify the top ASNs associated with failed login attempts:",[296,2972,2976],{"className":2973,"code":2974,"language":2975,"meta":301,"style":301},"language-spl shiki shiki-themes light-plus light-plus dracula","index=production sourcetype=api_logs endpoint=\"\u002Fapi\u002Fv1\u002Flogin\" status=401\n| stats count by ip_intelligence.asn.name, ip_intelligence.asn.type\n| sort - count\n| head 20\n","spl",[303,2977,2978,2983,2988,2993],{"__ignoreMap":301},[306,2979,2980],{"class":308,"line":309},[306,2981,2982],{},"index=production sourcetype=api_logs endpoint=\"\u002Fapi\u002Fv1\u002Flogin\" status=401\n",[306,2984,2985],{"class":308,"line":315},[306,2986,2987],{},"| stats count by ip_intelligence.asn.name, ip_intelligence.asn.type\n",[306,2989,2990],{"class":308,"line":321},[306,2991,2992],{},"| sort - count\n",[306,2994,2995],{"class":308,"line":327},[306,2996,2997],{},"| head 20\n",[225,2999,3000],{},"This query instantly reveals if a specific datacenter or proxy network is currently targeting your authentication endpoints, allowing your security team to respond proactively.",[238,3002,3004],{"id":3003},"conclusion","Conclusion",[225,3006,3007],{},"The era of simple IP blocking is over. The commoditization of residential proxy networks has fundamentally shifted the balance of power, granting attackers the ability to blend seamlessly into legitimate user traffic.",[225,3009,3010],{},"To survive in this environment, your applications must become contextually aware. By integrating deep network intelligence from tools like IP Shield into your authentication flows, edge routers, and monitoring dashboards, you regain visibility. You transition from a static, reactive security posture to a dynamic, adaptive defense capable of thwarting the most sophisticated modern attacks.",[225,3012,3013],{},"Security is not a final destination; it is a continuous arms race. Equip your infrastructure with the intelligence it needs to win.",[3015,3016,3017],"style",{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sZ328, html code.shiki .sZ328{--shiki-light:#AF00DB;--shiki-default:#AF00DB;--shiki-dark:#FF79C6}html pre.shiki code .sDd4n, html code.shiki .sDd4n{--shiki-light:#000000;--shiki-default:#000000;--shiki-dark:#F8F8F2}html pre.shiki code .sjsA6, html code.shiki .sjsA6{--shiki-light:#001080;--shiki-default:#001080;--shiki-dark:#F8F8F2}html pre.shiki code .sFkSl, html code.shiki .sFkSl{--shiki-light:#A31515;--shiki-default:#A31515;--shiki-dark:#E9F284}html pre.shiki code .sFB1V, html code.shiki .sFB1V{--shiki-light:#A31515;--shiki-default:#A31515;--shiki-dark:#F1FA8C}html pre.shiki code .sghk6, html code.shiki .sghk6{--shiki-light:#008000;--shiki-default:#008000;--shiki-dark:#6272A4}html pre.shiki code .sl46w, html code.shiki .sl46w{--shiki-light:#0000FF;--shiki-default:#0000FF;--shiki-dark:#FF79C6}html pre.shiki code .s3JHE, html code.shiki .s3JHE{--shiki-light:#0070C1;--shiki-default:#0070C1;--shiki-dark:#F8F8F2}html pre.shiki code .saOXh, html code.shiki .saOXh{--shiki-light:#000000;--shiki-default:#000000;--shiki-dark:#FF79C6}html pre.shiki code .sakC6, html code.shiki .sakC6{--shiki-light:#0000FF;--shiki-light-font-weight:inherit;--shiki-default:#0000FF;--shiki-default-font-weight:inherit;--shiki-dark:#FF79C6;--shiki-dark-font-weight:bold}html pre.shiki code .sHOzp, html code.shiki .sHOzp{--shiki-light:#795E26;--shiki-default:#795E26;--shiki-dark:#50FA7B}html pre.shiki code .sPzPf, html code.shiki .sPzPf{--shiki-light:#0070C1;--shiki-default:#0070C1;--shiki-dark:#BD93F9}html pre.shiki code .sygFZ, html code.shiki .sygFZ{--shiki-light:#001080;--shiki-light-font-style:inherit;--shiki-default:#001080;--shiki-default-font-style:inherit;--shiki-dark:#FFB86C;--shiki-dark-font-style:italic}html pre.shiki code .s34zl, html code.shiki .s34zl{--shiki-light:#001080;--shiki-default:#001080;--shiki-dark:#FF79C6}html pre.shiki code .sjR7W, html code.shiki .sjR7W{--shiki-light:#0000FF;--shiki-default:#0000FF;--shiki-dark:#BD93F9}html pre.shiki code .spgvN, html code.shiki .spgvN{--shiki-light:#098658;--shiki-default:#098658;--shiki-dark:#BD93F9}html pre.shiki code .sFs1U, html code.shiki .sFs1U{--shiki-light:#267F99;--shiki-light-font-style:inherit;--shiki-default:#267F99;--shiki-default-font-style:inherit;--shiki-dark:#8BE9FD;--shiki-dark-font-style:italic}html pre.shiki code .s1lnM, html code.shiki .s1lnM{--shiki-light:#000000FF;--shiki-default:#000000FF;--shiki-dark:#F8F8F2}",{"title":301,"searchDepth":315,"depth":315,"links":3019},[3020,3024,3029,3032,3037,3040,3044,3045],{"id":240,"depth":315,"text":241,"children":3021},[3022,3023],{"id":248,"depth":321,"text":249},{"id":284,"depth":321,"text":285},{"id":375,"depth":315,"text":376,"children":3025},[3026,3027,3028],{"id":382,"depth":321,"text":383},{"id":389,"depth":321,"text":390},{"id":396,"depth":321,"text":397},{"id":409,"depth":315,"text":410,"children":3030},[3031],{"id":419,"depth":321,"text":420},{"id":432,"depth":315,"text":433,"children":3033},[3034,3035,3036],{"id":439,"depth":321,"text":440},{"id":1520,"depth":321,"text":1521},{"id":2239,"depth":321,"text":2240},{"id":2875,"depth":315,"text":2876,"children":3038},[3039],{"id":2896,"depth":321,"text":2897},{"id":2936,"depth":315,"text":2937,"children":3041},[3042,3043],{"id":2943,"depth":321,"text":2944},{"id":2953,"depth":321,"text":2954},{"id":2963,"depth":315,"text":2964},{"id":3003,"depth":315,"text":3004},"2026-06-11","A comprehensive, deep-dive guide into protecting your infrastructure against residential proxies, commercial VPNs, and account takeover attacks using advanced IP intelligence and behavioral analytics.","md",null,"https:\u002F\u002Fimages.unsplash.com\u002Fphoto-1558494949-ef010cbdcc31?auto=format&fit=crop&q=80&w=800",{},"---\ntitle: Combating Residential Proxies and VPNs in Modern Applications\ndescription: A comprehensive, deep-dive guide into protecting your infrastructure against residential proxies, commercial VPNs, and account takeover attacks using advanced IP intelligence and behavioral analytics.\ntags: [\"security\", \"api\", \"fraud-prevention\", \"architecture\", \"networking\"]\nimage: \"https:\u002F\u002Fimages.unsplash.com\u002Fphoto-1558494949-ef010cbdcc31?auto=format&fit=crop&q=80&w=800\"\nauthor: \"Sergio\"\nauthorImg: \"https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F187537278?v=4\"\nauthorGithub: \"https:\u002F\u002Fgithub.com\u002FSergo706\"\nauthorGithubUserName: \"Sergo706\"\nfeatured: true\ndate: 2026-06-11T00:00:00.000Z\nreadingTime: \"35 min\"\n---\n\n# Combating Residential Proxies and VPNs in Modern Applications\n\nProtecting modern web applications requires significantly more than just checking an IP address against a static blocklist. Attackers constantly evolve their techniques. They leverage residential proxies and commercial VPN networks to mask their true origin and bypass rate limits. \n\nThe security industry faces a continuous and escalating challenge. Traditional security layers struggle to differentiate between a legitimate user logging in from their home internet and an automated script routing traffic through a compromised residential proxy network. This comprehensive guide explores the mechanics of residential proxies, the economics driving their use, and the technical strategies you must implement to defend your infrastructure.\n\n::note\nA residential proxy routes traffic through an actual residential internet connection. This makes the traffic appear as though it originates from a standard home user rather than a datacenter, effectively bypassing traditional IP-based filtering.\n::\n\n## The Anatomy of the Threat Landscape\n\nTo effectively defend against a threat, you must first understand how it operates at a fundamental level. The proxy ecosystem is vast, complex, and highly commercialized.\n\n### Types of IP Addresses Used by Attackers\n\nAttackers utilize several categories of IP addresses, each with distinct characteristics and risk profiles:\n\n1. **Datacenter IPs**: These are IP addresses assigned to massive server farms and cloud providers like AWS, Google Cloud, DigitalOcean, and Hetzner. They are cheap, fast, and highly available. However, they are also incredibly easy to detect and block. Legitimate consumers rarely browse the web from an AWS data center.\n2. **Commercial VPNs**: Services like NordVPN, ExpressVPN, and ProtonVPN route user traffic through shared egress IPs. While often used by privacy-conscious individuals, attackers heavily abuse them to mask their geographic location and true identity.\n3. **Residential Proxies**: These IPs belong to standard Internet Service Providers (ISPs) like Comcast, AT&T, and BT. They are attached to actual residential homes. Traffic originating from these IPs carries an inherently high reputation.\n4. **Mobile Proxies**: Similar to residential proxies, but the IPs belong to cellular carriers (e.g., Verizon, T-Mobile, Vodafone). These are the most difficult to block because thousands of legitimate users often share a single mobile IP via Carrier-Grade NAT (CGNAT).\n\n### How Residential Proxy Networks are Built\n\nUnderstanding how attackers acquire residential IPs is critical. They do not purchase these directly from ISPs. Instead, residential proxy networks are formed through various methods, many of which reside in an ethical gray area or are outright illegal.\n\nSome networks operate legitimately by offering users free software or premium features in exchange for sharing their idle bandwidth. Users agree to the terms of service, effectively turning their home router or computer into an exit node for the proxy network.\n\nHowever, many residential proxy networks are botnets built via malware. Attackers infect thousands of IoT devices, smart TVs, home routers, and personal computers. They then sell access to this compromised network to other malicious actors on the dark web or through shady proxy reselling platforms.\n\n```mermaid\ngraph TD\n    A[Attacker \u002F Scraper Script] -->|Routes Traffic| B(Proxy Network Controller)\n    B --> C[Infected Smart TV]\n    B --> D[Compromised Router]\n    B --> E[User running 'Free' VPN Extension]\n    C -->|Requests| F[Your Application]\n    D -->|Requests| F[Your Application]\n    E -->|Requests| F[Your Application]\n    \n    style A fill:#ffcccc,stroke:#ff0000,stroke-width:2px\n    style F fill:#ccffcc,stroke:#00aa00,stroke-width:2px\n```\n\n## The Economic Incentives\n\nWhy do attackers go through the trouble and expense of using residential proxies? The answer lies in the massive return on investment (ROI) available in digital fraud.\n\n### Account Takeover (ATO) and Credential Stuffing\n\nAttackers purchase massive databases of leaked usernames and passwords. They write scripts to test these credentials against your login endpoints. If they use a single datacenter IP, your rate-limiting rules block them after a few dozen attempts. By routing the requests through thousands of residential proxies, they stay under the rate-limit thresholds and blend in with regular login traffic.\n\n### E-commerce Scalping and Inventory Hoarding\n\nWhen highly anticipated products drop—such as limited-edition sneakers, concert tickets, or next-generation gaming consoles—scalping bots swarm the site. They use residential proxies to bypass per-IP purchase limits. Scalpers can generate millions of dollars in secondary market profits, easily justifying the cost of premium residential proxy subscriptions.\n\n### Payment Fraud and Carding\n\nAttackers use stolen credit card information to purchase digital goods or physical items. They use residential proxies located in the same city or zip code as the stolen credit card's billing address. This geographic consistency easily bypasses simplistic fraud detection systems that flag long-distance mismatches.\n\n::warning\nBlocking entire ISPs or geographic regions to stop these attacks often leads to unacceptable false positive rates. You lock out genuine customers while attempting to stop a handful of malicious actors.\n::\n\n## Utilizing Deep Network Intelligence\n\nIP Shield resolves this challenge by providing deep network intelligence on every request. The platform analyzes the IP address and returns a comprehensive metadata payload. This includes VPN detection flags, proxy network associations, Tor exit node identification, and precise ASN details.\n\nYou use this intelligence to introduce adaptive friction into your user flows. Rather than outright blocking an IP, you challenge high-risk connections with a CAPTCHA, require multi-factor authentication (MFA), or flag the account for manual review.\n\n### The Role of the Autonomous System Number (ASN)\n\nThe Internet is a network of networks. An Autonomous System (AS) is a large network or group of networks that has a unified routing policy. Every AS is assigned an Autonomous System Number (ASN). \n\nBy evaluating the ASN, you determine the organization responsible for the IP address. If the ASN belongs to a known consumer ISP like \"Comcast Cable Communications,\" the traffic is likely residential. If the ASN belongs to \"DigitalOcean, LLC,\" the traffic is from a datacenter.\n\nIP Shield provides the ASN data instantly. You filter traffic based on the network type. For example, you easily block all traffic originating from hosting providers on your consumer-facing login routes, while allowing cellular and residential networks to pass unhindered.\n\n## Implementing the Defense in Code\n\nDefending against residential proxies demands a dynamic security posture. You must integrate real-time intelligence into your edge compute layer or application backend. By doing so, you automatically filter out the noise and focus your resources on serving legitimate users.\n\n### Nuxt 3 and h3 Implementation\n\nIf you are using the modern Nuxt 3 stack, you integrate the IP Shield Network API directly into your server API routes or middleware. You evaluate the IP address before processing sensitive actions like logins, registrations, or checkouts.\n\nHere is an extensive example of how you build a robust, production-ready login handler using Nuxt 3, handling edge cases, proxy headers, and implementing adaptive friction.\n\n~~~typescript [server\u002Fapi\u002Flogin.post.ts]\nimport { IPShield } from '@ip-shield\u002Fsdk';\nimport { sendError, setResponseStatus, createError } from 'h3';\n\n\u002F\u002F Initialize the IP Shield SDK with your secure API key\nconst shield = new IPShield(process.env.IP_SHIELD_API_KEY);\n\nexport default defineEventHandler(async (event) => {\n  \u002F\u002F 1. Safely extract the client IP address\n  \u002F\u002F When behind a CDN or Load Balancer (Cloudflare, AWS ALB), the direct \n  \u002F\u002F connection IP belongs to the CDN. We must inspect the X-Forwarded-For header.\n  const ip = getRequestIP(event, { xForwardedFor: true });\n  \n  if (!ip) {\n    throw createError({\n      statusCode: 400,\n      statusMessage: 'Unable to determine client IP address'\n    });\n  }\n\n  const body = await readBody(event);\n  \n  \u002F\u002F 2. Perform the IP Intelligence Lookup\n  \u002F\u002F We use a try-catch block to ensure that if the IP Shield API is unreachable \n  \u002F\u002F due to network issues, we fail open or handle it gracefully rather than \n  \u002F\u002F blocking all user logins.\n  let networkData;\n  try {\n    networkData = await shield.network.lookup(ip);\n  } catch (err) {\n    console.error('IP Shield lookup failed, failing open for availability', err);\n    \u002F\u002F Proceed with standard authentication, but log the failure\n    return authenticateUser(body.email, body.password);\n  }\n  \n  \u002F\u002F 3. Analyze the Threat Vectors\n  const isHighRisk = networkData.isProxy || networkData.isVpn || networkData.isTor;\n  const isDatacenter = networkData.asn.type === 'hosting';\n  \n  \u002F\u002F 4. Execute the Security Policy\n  if (networkData.isTor) {\n    \u002F\u002F Tor traffic is almost exclusively malicious in an e-commerce context.\n    \u002F\u002F We block it outright.\n    setResponseStatus(event, 403);\n    return { \n      error: 'access_denied', \n      message: 'Connections from the Tor network are not permitted.' \n    };\n  }\n\n  if (isDatacenter) {\n    \u002F\u002F Legitimate users do not log in from AWS servers. This is likely a script.\n    setResponseStatus(event, 403);\n    return { \n      error: 'access_denied', \n      message: 'Datacenter IP ranges are not permitted. Please disable your VPN.' \n    };\n  }\n\n  if (isHighRisk) {\n    \u002F\u002F The IP belongs to a residential proxy or commercial VPN. \n    \u002F\u002F It might be a malicious actor, or it might be a privacy-conscious user.\n    \u002F\u002F We do NOT block them outright. Instead, we introduce adaptive friction.\n    setResponseStatus(event, 401);\n    return { \n      error: 'verification_required', \n      challengeType: 'mfa',\n      message: 'Unusual network detected. Please enter the code sent to your mobile device.' \n    };\n  }\n  \n  \u002F\u002F 5. If all checks pass, proceed with standard authentication\n  const authResult = await authenticateUser(body.email, body.password);\n  \n  if (!authResult.success) {\n    \u002F\u002F Even if the IP is safe, standard credential checks still apply\n    throw createError({\n      statusCode: 401,\n      statusMessage: 'Invalid credentials'\n    });\n  }\n\n  return {\n    success: true,\n    token: authResult.token,\n    user: authResult.user\n  };\n});\n~~~\n\n::tip\nAlways test your IP extraction logic thoroughly. Misconfiguring the `x-forwarded-for` header parsing can lead to IP spoofing vulnerabilities, where an attacker injects a fake IP address to bypass your security checks.\n::\n\n### Express.js Implementation\n\nIf your backend is built on traditional Express.js, the concepts remain identical, though the implementation syntax differs slightly. You implement this as a reusable middleware function that you attach to specific high-risk routes.\n\n~~~javascript [middleware\u002FipIntelligence.js]\nconst { IPShield } = require('@ip-shield\u002Fsdk');\nconst shield = new IPShield(process.env.IP_SHIELD_API_KEY);\n\n\u002F**\n * Express middleware to evaluate IP risk before processing requests\n *\u002F\nasync function ipIntelligenceMiddleware(req, res, next) {\n  \u002F\u002F Extract IP, respecting trust proxy settings in Express\n  const ip = req.ip;\n\n  try {\n    const networkData = await shield.network.lookup(ip);\n    \n    \u002F\u002F Attach the intelligence data to the request object for downstream use\n    req.ipIntelligence = networkData;\n\n    \u002F\u002F Hard block for Tor and Datacenters\n    if (networkData.isTor || networkData.asn.type === 'hosting') {\n      return res.status(403).json({\n        error: 'Forbidden',\n        message: 'Your network type is not permitted to access this resource.'\n      });\n    }\n\n    \u002F\u002F Flag for downstream adaptive friction\n    if (networkData.isProxy || networkData.isVpn) {\n      req.requiresMfa = true;\n    }\n\n    next();\n  } catch (error) {\n    console.error('IP Shield API Error:', error);\n    \u002F\u002F Fail open to prevent locking out legitimate users during an outage\n    next();\n  }\n}\n\nmodule.exports = ipIntelligenceMiddleware;\n~~~\n\nYou then apply this middleware to your sensitive routes:\n\n~~~javascript [routes\u002Fauth.js]\nconst express = require('express');\nconst router = express.Router();\nconst ipIntelligence = require('..\u002Fmiddleware\u002FipIntelligence');\n\n\u002F\u002F Apply the IP intelligence middleware specifically to the login route\nrouter.post('\u002Flogin', ipIntelligence, async (req, res) => {\n  const { email, password } = req.body;\n\n  \u002F\u002F Check if the middleware flagged this request for MFA\n  if (req.requiresMfa) {\n    return res.status(401).json({\n      error: 'MFA_REQUIRED',\n      message: 'Please complete multi-factor authentication.'\n    });\n  }\n\n  \u002F\u002F Standard login logic...\n  res.json({ success: true });\n});\n\nmodule.exports = router;\n~~~\n\n### Implementing at the Edge with Cloudflare Workers\n\nFor maximum performance, you move your security logic as close to the user as possible. Cloudflare Workers allow you to intercept requests at the CDN edge, before they ever reach your origin server. This protects your backend infrastructure from the computational load of processing malicious requests.\n\n~~~javascript [worker.js]\nexport default {\n  async fetch(request, env, ctx) {\n    const url = new URL(request.url);\n    \n    \u002F\u002F Only run the heavy IP check on sensitive endpoints to save costs and latency\n    if (url.pathname !== '\u002Fapi\u002Fv1\u002Flogin' && url.pathname !== '\u002Fapi\u002Fv1\u002Fcheckout') {\n      return fetch(request);\n    }\n\n    \u002F\u002F Cloudflare provides the client IP in the headers\n    const clientIP = request.headers.get('CF-Connecting-IP');\n\n    try {\n      \u002F\u002F Make a subrequest to the IP Shield API\n      const shieldResponse = await fetch(`https:\u002F\u002Fip-shield.riavzon.com\u002Fv1\u002Fnetwork\u002F${clientIP}`, {\n        headers: {\n          'Authorization': `Bearer ${env.IP_SHIELD_API_KEY}`\n        }\n      });\n\n      if (shieldResponse.ok) {\n        const networkData = await shieldResponse.json();\n\n        \u002F\u002F Implement blocking logic at the edge\n        if (networkData.isTor || networkData.asn.type === 'hosting') {\n          return new Response(JSON.stringify({ error: 'Access Denied' }), {\n            status: 403,\n            headers: { 'Content-Type': 'application\u002Fjson' }\n          });\n        }\n        \n        \u002F\u002F Pass intelligence data to the origin server via custom headers\n        const modifiedRequest = new Request(request);\n        if (networkData.isProxy || networkData.isVpn) {\n          modifiedRequest.headers.set('X-Requires-Adaptive-Friction', 'true');\n        }\n        \n        return fetch(modifiedRequest);\n      }\n    } catch (err) {\n      \u002F\u002F Fail open on error\n      console.error('Edge security check failed:', err);\n    }\n\n    return fetch(request);\n  }\n};\n~~~\n\n::important\nWhen implementing edge security, always ensure your origin server is configured to ONLY accept traffic from your Edge provider (e.g., Cloudflare IP ranges). Otherwise, attackers simply bypass the edge worker by connecting to your origin IP directly.\n::\n\n## The Challenge of IPv6 and Subnet Hopping\n\nAs the internet transitions to IPv6, attackers gain access to an unimaginably large address space. Traditional IPv4 blocklists fail against IPv6 because an attacker can cycle through billions of IP addresses within a single `\u002F64` subnet.\n\nWhen dealing with IPv6, you must adjust your defensive strategies. You no longer block or evaluate individual `\u002F128` IP addresses. Instead, you apply your logic to the entire `\u002F64` subnet. IP Shield handles this complexity automatically, aggregating intelligence across IPv6 blocks so that if an attacker hops IPs within their assigned subnet, the threat score remains accurate.\n\n### Subnet Aggregation Strategies\n\n1. **IPv4**: Track and evaluate on a `\u002F32` (individual IP) or `\u002F24` (C-class subnet) basis.\n2. **IPv6**: Always track and evaluate on a minimum of a `\u002F64` basis.\n\nIf you observe malicious activity from `2001:db8:1234:5678:90ab:cdef:0123:4567`, you should apply security friction to the entire `2001:db8:1234:5678::\u002F64` range.\n\n## Advanced Techniques: Correlating Signals\n\nIP intelligence is incredibly powerful, but it becomes exponentially more effective when combined with other security signals. To build a truly resilient system against advanced residential proxies, you must correlate network data with client-side telemetry.\n\n### Device Fingerprinting\n\nAttackers using residential proxies often route traffic from hundreds of IPs, but they might use the same underlying hardware or scraping script for all requests. By implementing device fingerprinting—analyzing the Canvas API rendering, WebGL drivers, audio context, and font stacks—you generate a unique identifier for the machine making the request.\n\nIf you observe 500 different residential IPs logging into 500 different accounts, but all 500 requests share the exact same highly unique device fingerprint, you definitively identify an ongoing attack.\n\n### Behavioral Biometrics\n\nHow does the user interact with the page? Does the mouse move in perfectly straight lines? Are keystrokes registering with zero variance in timing? Human behavior is messy and unpredictable. Scrapers and bots, even those using residential proxies, often exhibit robotic perfection.\n\nBy combining IP Shield's network data with behavioral biometrics, you achieve unprecedented detection accuracy.\n\n## Creating a Splunk Dashboard for Traffic Analysis\n\nMonitoring your traffic is just as important as blocking it. By logging the IP Shield metadata alongside your standard access logs, you create powerful visualizations in tools like Splunk, ELK (Elasticsearch, Logstash, Kibana), or Datadog.\n\nHere is an example Splunk SPL query to identify the top ASNs associated with failed login attempts:\n\n```spl\nindex=production sourcetype=api_logs endpoint=\"\u002Fapi\u002Fv1\u002Flogin\" status=401\n| stats count by ip_intelligence.asn.name, ip_intelligence.asn.type\n| sort - count\n| head 20\n```\n\nThis query instantly reveals if a specific datacenter or proxy network is currently targeting your authentication endpoints, allowing your security team to respond proactively.\n\n## Conclusion\n\nThe era of simple IP blocking is over. The commoditization of residential proxy networks has fundamentally shifted the balance of power, granting attackers the ability to blend seamlessly into legitimate user traffic.\n\nTo survive in this environment, your applications must become contextually aware. By integrating deep network intelligence from tools like IP Shield into your authentication flows, edge routers, and monitoring dashboards, you regain visibility. You transition from a static, reactive security posture to a dynamic, adaptive defense capable of thwarting the most sophisticated modern attacks.\n\nSecurity is not a final destination; it is a continuous arms race. Equip your infrastructure with the intelligence it needs to win.\n","35 min",{"title":129,"description":3047},[3056,3057,3058,3059,3060],"security","api","fraud-prevention","architecture","networking","b6CYd4tNLDxwFPDFru5A8e_pI5HYGT4oPX9HIBKLUxQ",{"id":212,"title":129,"author":213,"authorGithub":214,"authorGithubUserName":215,"authorImg":216,"body":3063,"date":3046,"description":3047,"extension":3048,"featured":10,"icon":3049,"image":3050,"meta":5363,"navigation":10,"path":130,"rawbody":3052,"readingTime":3053,"seo":5364,"stem":131,"tags":5365,"__hash__":3061},{"type":218,"value":3064,"toc":5335},[3065,3067,3069,3071,3075,3077,3079,3081,3083,3101,3103,3105,3107,3109,3157,3159,3161,3163,3165,3167,3169,3171,3173,3177,3179,3181,3183,3185,3187,3189,3191,3193,3195,3197,3199,3201,4027,4033,4035,4037,4431,4433,4687,4689,4691,5241,5245,5247,5251,5257,5259,5275,5281,5283,5285,5287,5289,5291,5293,5295,5297,5299,5301,5303,5323,5325,5327,5329,5331,5333],[221,3066,129],{"id":223},[225,3068,227],{},[225,3070,230],{},[232,3072,3073],{},[225,3074,236],{},[238,3076,241],{"id":240},[225,3078,244],{},[246,3080,249],{"id":248},[225,3082,252],{},[254,3084,3085,3089,3093,3097],{},[257,3086,3087,263],{},[260,3088,262],{},[257,3090,3091,269],{},[260,3092,268],{},[257,3094,3095,275],{},[260,3096,274],{},[257,3098,3099,281],{},[260,3100,280],{},[246,3102,285],{"id":284},[225,3104,288],{},[225,3106,291],{},[225,3108,294],{},[296,3110,3111],{"className":298,"code":299,"language":300,"meta":301,"style":301},[303,3112,3113,3117,3121,3125,3129,3133,3137,3141,3145,3149,3153],{"__ignoreMap":301},[306,3114,3115],{"class":308,"line":309},[306,3116,312],{},[306,3118,3119],{"class":308,"line":315},[306,3120,318],{},[306,3122,3123],{"class":308,"line":321},[306,3124,324],{},[306,3126,3127],{"class":308,"line":327},[306,3128,330],{},[306,3130,3131],{"class":308,"line":333},[306,3132,336],{},[306,3134,3135],{"class":308,"line":339},[306,3136,342],{},[306,3138,3139],{"class":308,"line":345},[306,3140,348],{},[306,3142,3143],{"class":308,"line":351},[306,3144,354],{},[306,3146,3147],{"class":308,"line":357},[306,3148,360],{},[306,3150,3151],{"class":308,"line":363},[306,3152,366],{},[306,3154,3155],{"class":308,"line":369},[306,3156,372],{},[238,3158,376],{"id":375},[225,3160,379],{},[246,3162,383],{"id":382},[225,3164,386],{},[246,3166,390],{"id":389},[225,3168,393],{},[246,3170,397],{"id":396},[225,3172,400],{},[402,3174,3175],{},[225,3176,406],{},[238,3178,410],{"id":409},[225,3180,413],{},[225,3182,416],{},[246,3184,420],{"id":419},[225,3186,423],{},[225,3188,426],{},[225,3190,429],{},[238,3192,433],{"id":432},[225,3194,436],{},[246,3196,440],{"id":439},[225,3198,443],{},[225,3200,446],{},[296,3202,3203],{"className":449,"code":450,"filename":451,"language":452,"meta":301,"style":301},[303,3204,3205,3225,3253,3257,3261,3287,3291,3313,3317,3321,3325,3349,3353,3365,3373,3383,3395,3399,3403,3407,3425,3429,3433,3437,3441,3445,3453,3459,3483,3495,3517,3521,3545,3549,3553,3557,3589,3617,3621,3625,3639,3643,3647,3661,3667,3681,3695,3699,3703,3707,3717,3721,3735,3741,3755,3769,3773,3777,3781,3791,3795,3799,3803,3817,3823,3837,3851,3865,3869,3873,3877,3881,3911,3915,3931,3935,3943,3953,3965,3969,3973,3977,3983,3993,4007,4019,4023],{"__ignoreMap":301},[306,3206,3207,3209,3211,3213,3215,3217,3219,3221,3223],{"class":308,"line":309},[306,3208,460],{"class":459},[306,3210,464],{"class":463},[306,3212,468],{"class":467},[306,3214,471],{"class":463},[306,3216,474],{"class":459},[306,3218,478],{"class":477},[306,3220,482],{"class":481},[306,3222,485],{"class":477},[306,3224,488],{"class":463},[306,3226,3227,3229,3231,3233,3235,3237,3239,3241,3243,3245,3247,3249,3251],{"class":308,"line":315},[306,3228,460],{"class":459},[306,3230,464],{"class":463},[306,3232,497],{"class":467},[306,3234,500],{"class":463},[306,3236,503],{"class":467},[306,3238,500],{"class":463},[306,3240,508],{"class":467},[306,3242,471],{"class":463},[306,3244,474],{"class":459},[306,3246,478],{"class":477},[306,3248,246],{"class":481},[306,3250,485],{"class":477},[306,3252,488],{"class":463},[306,3254,3255],{"class":308,"line":321},[306,3256,525],{"emptyLinePlaceholder":10},[306,3258,3259],{"class":308,"line":327},[306,3260,531],{"class":530},[306,3262,3263,3265,3267,3269,3271,3273,3275,3277,3279,3281,3283,3285],{"class":308,"line":333},[306,3264,537],{"class":536},[306,3266,541],{"class":540},[306,3268,545],{"class":544},[306,3270,549],{"class":548},[306,3272,553],{"class":552},[306,3274,556],{"class":463},[306,3276,559],{"class":467},[306,3278,562],{"class":463},[306,3280,565],{"class":467},[306,3282,562],{"class":463},[306,3284,571],{"class":570},[306,3286,574],{"class":463},[306,3288,3289],{"class":308,"line":339},[306,3290,525],{"emptyLinePlaceholder":10},[306,3292,3293,3295,3297,3299,3301,3303,3305,3307,3309,3311],{"class":308,"line":345},[306,3294,583],{"class":459},[306,3296,586],{"class":459},[306,3298,589],{"class":552},[306,3300,556],{"class":463},[306,3302,594],{"class":536},[306,3304,597],{"class":463},[306,3306,601],{"class":600},[306,3308,604],{"class":463},[306,3310,607],{"class":536},[306,3312,610],{"class":463},[306,3314,3315],{"class":308,"line":351},[306,3316,615],{"class":530},[306,3318,3319],{"class":308,"line":357},[306,3320,620],{"class":530},[306,3322,3323],{"class":308,"line":363},[306,3324,625],{"class":530},[306,3326,3327,3329,3331,3333,3335,3337,3339,3341,3343,3345,3347],{"class":308,"line":369},[306,3328,630],{"class":536},[306,3330,633],{"class":540},[306,3332,545],{"class":544},[306,3334,638],{"class":552},[306,3336,556],{"class":463},[306,3338,601],{"class":467},[306,3340,645],{"class":463},[306,3342,648],{"class":467},[306,3344,652],{"class":651},[306,3346,656],{"class":655},[306,3348,659],{"class":463},[306,3350,3351],{"class":308,"line":662},[306,3352,665],{"class":463},[306,3354,3355,3357,3359,3361,3363],{"class":308,"line":668},[306,3356,671],{"class":459},[306,3358,597],{"class":463},[306,3360,676],{"class":544},[306,3362,679],{"class":467},[306,3364,682],{"class":463},[306,3366,3367,3369,3371],{"class":308,"line":685},[306,3368,688],{"class":459},[306,3370,691],{"class":552},[306,3372,694],{"class":463},[306,3374,3375,3377,3379,3381],{"class":308,"line":697},[306,3376,700],{"class":467},[306,3378,652],{"class":651},[306,3380,706],{"class":705},[306,3382,709],{"class":463},[306,3384,3385,3387,3389,3391,3393],{"class":308,"line":712},[306,3386,715],{"class":467},[306,3388,652],{"class":651},[306,3390,478],{"class":477},[306,3392,722],{"class":481},[306,3394,725],{"class":477},[306,3396,3397],{"class":308,"line":728},[306,3398,731],{"class":463},[306,3400,3401],{"class":308,"line":734},[306,3402,737],{"class":463},[306,3404,3405],{"class":308,"line":740},[306,3406,525],{"emptyLinePlaceholder":10},[306,3408,3409,3411,3413,3415,3417,3419,3421,3423],{"class":308,"line":745},[306,3410,630],{"class":536},[306,3412,750],{"class":540},[306,3414,545],{"class":544},[306,3416,755],{"class":459},[306,3418,758],{"class":552},[306,3420,556],{"class":463},[306,3422,601],{"class":467},[306,3424,574],{"class":463},[306,3426,3427],{"class":308,"line":767},[306,3428,665],{"class":463},[306,3430,3431],{"class":308,"line":772},[306,3432,775],{"class":530},[306,3434,3435],{"class":308,"line":778},[306,3436,781],{"class":530},[306,3438,3439],{"class":308,"line":784},[306,3440,787],{"class":530},[306,3442,3443],{"class":308,"line":790},[306,3444,793],{"class":530},[306,3446,3447,3449,3451],{"class":308,"line":796},[306,3448,799],{"class":536},[306,3450,802],{"class":467},[306,3452,488],{"class":463},[306,3454,3455,3457],{"class":308,"line":807},[306,3456,810],{"class":459},[306,3458,610],{"class":463},[306,3460,3461,3463,3465,3467,3469,3471,3473,3475,3477,3479,3481],{"class":308,"line":815},[306,3462,818],{"class":467},[306,3464,545],{"class":544},[306,3466,755],{"class":459},[306,3468,541],{"class":467},[306,3470,562],{"class":463},[306,3472,829],{"class":467},[306,3474,562],{"class":463},[306,3476,834],{"class":552},[306,3478,556],{"class":463},[306,3480,679],{"class":467},[306,3482,574],{"class":463},[306,3484,3485,3487,3489,3491,3493],{"class":308,"line":843},[306,3486,846],{"class":463},[306,3488,849],{"class":459},[306,3490,597],{"class":463},[306,3492,854],{"class":467},[306,3494,682],{"class":463},[306,3496,3497,3499,3501,3503,3505,3507,3509,3511,3513,3515],{"class":308,"line":859},[306,3498,862],{"class":467},[306,3500,562],{"class":463},[306,3502,867],{"class":552},[306,3504,556],{"class":463},[306,3506,485],{"class":477},[306,3508,874],{"class":481},[306,3510,485],{"class":477},[306,3512,500],{"class":463},[306,3514,854],{"class":467},[306,3516,574],{"class":463},[306,3518,3519],{"class":308,"line":885},[306,3520,888],{"class":530},[306,3522,3523,3525,3527,3529,3531,3533,3535,3537,3539,3541,3543],{"class":308,"line":891},[306,3524,894],{"class":459},[306,3526,897],{"class":552},[306,3528,556],{"class":463},[306,3530,902],{"class":467},[306,3532,562],{"class":463},[306,3534,907],{"class":467},[306,3536,500],{"class":463},[306,3538,902],{"class":467},[306,3540,562],{"class":463},[306,3542,916],{"class":467},[306,3544,574],{"class":463},[306,3546,3547],{"class":308,"line":921},[306,3548,737],{"class":463},[306,3550,3551],{"class":308,"line":926},[306,3552,665],{"class":463},[306,3554,3555],{"class":308,"line":931},[306,3556,934],{"class":530},[306,3558,3559,3561,3563,3565,3567,3569,3571,3573,3575,3577,3579,3581,3583,3585,3587],{"class":308,"line":937},[306,3560,630],{"class":536},[306,3562,942],{"class":540},[306,3564,545],{"class":544},[306,3566,802],{"class":467},[306,3568,562],{"class":463},[306,3570,951],{"class":467},[306,3572,954],{"class":544},[306,3574,802],{"class":467},[306,3576,562],{"class":463},[306,3578,961],{"class":467},[306,3580,954],{"class":544},[306,3582,802],{"class":467},[306,3584,562],{"class":463},[306,3586,970],{"class":467},[306,3588,488],{"class":463},[306,3590,3591,3593,3595,3597,3599,3601,3603,3605,3607,3609,3611,3613,3615],{"class":308,"line":975},[306,3592,630],{"class":536},[306,3594,980],{"class":540},[306,3596,545],{"class":544},[306,3598,802],{"class":467},[306,3600,562],{"class":463},[306,3602,989],{"class":467},[306,3604,562],{"class":463},[306,3606,994],{"class":467},[306,3608,997],{"class":544},[306,3610,478],{"class":477},[306,3612,1002],{"class":481},[306,3614,485],{"class":477},[306,3616,488],{"class":463},[306,3618,3619],{"class":308,"line":1009},[306,3620,665],{"class":463},[306,3622,3623],{"class":308,"line":1014},[306,3624,1017],{"class":530},[306,3626,3627,3629,3631,3633,3635,3637],{"class":308,"line":1020},[306,3628,671],{"class":459},[306,3630,597],{"class":463},[306,3632,1027],{"class":467},[306,3634,562],{"class":463},[306,3636,970],{"class":467},[306,3638,682],{"class":463},[306,3640,3641],{"class":308,"line":1036},[306,3642,1039],{"class":530},[306,3644,3645],{"class":308,"line":1042},[306,3646,1045],{"class":530},[306,3648,3649,3651,3653,3655,3657,3659],{"class":308,"line":1048},[306,3650,1051],{"class":552},[306,3652,556],{"class":463},[306,3654,601],{"class":467},[306,3656,500],{"class":463},[306,3658,1060],{"class":705},[306,3660,574],{"class":463},[306,3662,3663,3665],{"class":308,"line":1065},[306,3664,894],{"class":459},[306,3666,1070],{"class":463},[306,3668,3669,3671,3673,3675,3677,3679],{"class":308,"line":1073},[306,3670,1076],{"class":467},[306,3672,652],{"class":651},[306,3674,478],{"class":477},[306,3676,1083],{"class":481},[306,3678,485],{"class":477},[306,3680,1088],{"class":463},[306,3682,3683,3685,3687,3689,3691,3693],{"class":308,"line":1091},[306,3684,1094],{"class":467},[306,3686,652],{"class":651},[306,3688,478],{"class":477},[306,3690,1101],{"class":481},[306,3692,485],{"class":477},[306,3694,1106],{"class":463},[306,3696,3697],{"class":308,"line":1109},[306,3698,1112],{"class":463},[306,3700,3701],{"class":308,"line":1115},[306,3702,737],{"class":463},[306,3704,3705],{"class":308,"line":1120},[306,3706,525],{"emptyLinePlaceholder":10},[306,3708,3709,3711,3713,3715],{"class":308,"line":1125},[306,3710,671],{"class":459},[306,3712,597],{"class":463},[306,3714,1132],{"class":467},[306,3716,682],{"class":463},[306,3718,3719],{"class":308,"line":1137},[306,3720,1140],{"class":530},[306,3722,3723,3725,3727,3729,3731,3733],{"class":308,"line":1143},[306,3724,1051],{"class":552},[306,3726,556],{"class":463},[306,3728,601],{"class":467},[306,3730,500],{"class":463},[306,3732,1060],{"class":705},[306,3734,574],{"class":463},[306,3736,3737,3739],{"class":308,"line":1158},[306,3738,894],{"class":459},[306,3740,1070],{"class":463},[306,3742,3743,3745,3747,3749,3751,3753],{"class":308,"line":1165},[306,3744,1076],{"class":467},[306,3746,652],{"class":651},[306,3748,478],{"class":477},[306,3750,1083],{"class":481},[306,3752,485],{"class":477},[306,3754,1088],{"class":463},[306,3756,3757,3759,3761,3763,3765,3767],{"class":308,"line":1180},[306,3758,1094],{"class":467},[306,3760,652],{"class":651},[306,3762,478],{"class":477},[306,3764,1189],{"class":481},[306,3766,485],{"class":477},[306,3768,1106],{"class":463},[306,3770,3771],{"class":308,"line":1196},[306,3772,1112],{"class":463},[306,3774,3775],{"class":308,"line":1201},[306,3776,737],{"class":463},[306,3778,3779],{"class":308,"line":1206},[306,3780,525],{"emptyLinePlaceholder":10},[306,3782,3783,3785,3787,3789],{"class":308,"line":1211},[306,3784,671],{"class":459},[306,3786,597],{"class":463},[306,3788,1218],{"class":467},[306,3790,682],{"class":463},[306,3792,3793],{"class":308,"line":1223},[306,3794,1226],{"class":530},[306,3796,3797],{"class":308,"line":1229},[306,3798,1232],{"class":530},[306,3800,3801],{"class":308,"line":1235},[306,3802,1238],{"class":530},[306,3804,3805,3807,3809,3811,3813,3815],{"class":308,"line":1241},[306,3806,1051],{"class":552},[306,3808,556],{"class":463},[306,3810,601],{"class":467},[306,3812,500],{"class":463},[306,3814,1252],{"class":705},[306,3816,574],{"class":463},[306,3818,3819,3821],{"class":308,"line":1257},[306,3820,894],{"class":459},[306,3822,1070],{"class":463},[306,3824,3825,3827,3829,3831,3833,3835],{"class":308,"line":1264},[306,3826,1076],{"class":467},[306,3828,652],{"class":651},[306,3830,478],{"class":477},[306,3832,1273],{"class":481},[306,3834,485],{"class":477},[306,3836,1088],{"class":463},[306,3838,3839,3841,3843,3845,3847,3849],{"class":308,"line":1280},[306,3840,1283],{"class":467},[306,3842,652],{"class":651},[306,3844,478],{"class":477},[306,3846,1290],{"class":481},[306,3848,485],{"class":477},[306,3850,709],{"class":463},[306,3852,3853,3855,3857,3859,3861,3863],{"class":308,"line":1297},[306,3854,1094],{"class":467},[306,3856,652],{"class":651},[306,3858,478],{"class":477},[306,3860,1306],{"class":481},[306,3862,485],{"class":477},[306,3864,1106],{"class":463},[306,3866,3867],{"class":308,"line":1313},[306,3868,1112],{"class":463},[306,3870,3871],{"class":308,"line":1318},[306,3872,737],{"class":463},[306,3874,3875],{"class":308,"line":1323},[306,3876,665],{"class":463},[306,3878,3879],{"class":308,"line":1328},[306,3880,1331],{"class":530},[306,3882,3883,3885,3887,3889,3891,3893,3895,3897,3899,3901,3903,3905,3907,3909],{"class":308,"line":1334},[306,3884,630],{"class":536},[306,3886,1339],{"class":540},[306,3888,545],{"class":544},[306,3890,755],{"class":459},[306,3892,897],{"class":552},[306,3894,556],{"class":463},[306,3896,902],{"class":467},[306,3898,562],{"class":463},[306,3900,907],{"class":467},[306,3902,500],{"class":463},[306,3904,902],{"class":467},[306,3906,562],{"class":463},[306,3908,916],{"class":467},[306,3910,574],{"class":463},[306,3912,3913],{"class":308,"line":1366},[306,3914,665],{"class":463},[306,3916,3917,3919,3921,3923,3925,3927,3929],{"class":308,"line":1371},[306,3918,671],{"class":459},[306,3920,597],{"class":463},[306,3922,676],{"class":544},[306,3924,1380],{"class":467},[306,3926,562],{"class":463},[306,3928,1385],{"class":467},[306,3930,682],{"class":463},[306,3932,3933],{"class":308,"line":1390},[306,3934,1393],{"class":530},[306,3936,3937,3939,3941],{"class":308,"line":1396},[306,3938,688],{"class":459},[306,3940,691],{"class":552},[306,3942,694],{"class":463},[306,3944,3945,3947,3949,3951],{"class":308,"line":1405},[306,3946,700],{"class":467},[306,3948,652],{"class":651},[306,3950,1412],{"class":705},[306,3952,709],{"class":463},[306,3954,3955,3957,3959,3961,3963],{"class":308,"line":1417},[306,3956,715],{"class":467},[306,3958,652],{"class":651},[306,3960,478],{"class":477},[306,3962,1426],{"class":481},[306,3964,725],{"class":477},[306,3966,3967],{"class":308,"line":1431},[306,3968,731],{"class":463},[306,3970,3971],{"class":308,"line":1436},[306,3972,737],{"class":463},[306,3974,3975],{"class":308,"line":1441},[306,3976,525],{"emptyLinePlaceholder":10},[306,3978,3979,3981],{"class":308,"line":1446},[306,3980,1449],{"class":459},[306,3982,610],{"class":463},[306,3984,3985,3987,3989,3991],{"class":308,"line":1454},[306,3986,1457],{"class":467},[306,3988,652],{"class":651},[306,3990,656],{"class":655},[306,3992,709],{"class":463},[306,3994,3995,3997,3999,4001,4003,4005],{"class":308,"line":1466},[306,3996,1469],{"class":467},[306,3998,652],{"class":651},[306,4000,1339],{"class":467},[306,4002,562],{"class":463},[306,4004,1478],{"class":467},[306,4006,709],{"class":463},[306,4008,4009,4011,4013,4015,4017],{"class":308,"line":1483},[306,4010,1486],{"class":467},[306,4012,652],{"class":651},[306,4014,1339],{"class":467},[306,4016,562],{"class":463},[306,4018,1495],{"class":467},[306,4020,4021],{"class":308,"line":1498},[306,4022,1501],{"class":463},[306,4024,4025],{"class":308,"line":1504},[306,4026,1507],{"class":463},[1509,4028,4029],{},[225,4030,1513,4031,1517],{},[303,4032,1516],{},[246,4034,1521],{"id":1520},[225,4036,1524],{},[296,4038,4039],{"className":1527,"code":1528,"filename":1529,"language":1530,"meta":301,"style":301},[303,4040,4041,4065,4091,4095,4099,4103,4107,4129,4133,4149,4153,4159,4185,4189,4193,4207,4211,4215,4249,4269,4283,4295,4299,4303,4307,4311,4333,4347,4351,4355,4361,4373,4395,4399,4405,4409,4413,4417],{"__ignoreMap":301},[306,4042,4043,4045,4047,4049,4051,4053,4055,4057,4059,4061,4063],{"class":308,"line":309},[306,4044,537],{"class":536},[306,4046,464],{"class":463},[306,4048,468],{"class":540},[306,4050,471],{"class":463},[306,4052,1545],{"class":544},[306,4054,1548],{"class":552},[306,4056,556],{"class":463},[306,4058,485],{"class":477},[306,4060,482],{"class":481},[306,4062,485],{"class":477},[306,4064,574],{"class":463},[306,4066,4067,4069,4071,4073,4075,4077,4079,4081,4083,4085,4087,4089],{"class":308,"line":315},[306,4068,537],{"class":536},[306,4070,541],{"class":540},[306,4072,545],{"class":544},[306,4074,549],{"class":548},[306,4076,553],{"class":552},[306,4078,556],{"class":463},[306,4080,559],{"class":467},[306,4082,562],{"class":463},[306,4084,565],{"class":467},[306,4086,562],{"class":463},[306,4088,571],{"class":570},[306,4090,574],{"class":463},[306,4092,4093],{"class":308,"line":321},[306,4094,525],{"emptyLinePlaceholder":10},[306,4096,4097],{"class":308,"line":327},[306,4098,1593],{"class":530},[306,4100,4101],{"class":308,"line":333},[306,4102,1598],{"class":530},[306,4104,4105],{"class":308,"line":339},[306,4106,1603],{"class":530},[306,4108,4109,4111,4113,4115,4117,4119,4121,4123,4125,4127],{"class":308,"line":345},[306,4110,594],{"class":536},[306,4112,1610],{"class":536},[306,4114,1613],{"class":552},[306,4116,556],{"class":463},[306,4118,1618],{"class":600},[306,4120,500],{"class":463},[306,4122,1623],{"class":600},[306,4124,500],{"class":463},[306,4126,1628],{"class":600},[306,4128,682],{"class":463},[306,4130,4131],{"class":308,"line":351},[306,4132,1635],{"class":530},[306,4134,4135,4137,4139,4141,4143,4145,4147],{"class":308,"line":357},[306,4136,630],{"class":536},[306,4138,633],{"class":540},[306,4140,545],{"class":544},[306,4142,1646],{"class":467},[306,4144,562],{"class":463},[306,4146,679],{"class":467},[306,4148,488],{"class":463},[306,4150,4151],{"class":308,"line":363},[306,4152,525],{"emptyLinePlaceholder":10},[306,4154,4155,4157],{"class":308,"line":369},[306,4156,810],{"class":459},[306,4158,610],{"class":463},[306,4160,4161,4163,4165,4167,4169,4171,4173,4175,4177,4179,4181,4183],{"class":308,"line":662},[306,4162,1667],{"class":536},[306,4164,802],{"class":540},[306,4166,545],{"class":544},[306,4168,755],{"class":459},[306,4170,541],{"class":467},[306,4172,562],{"class":463},[306,4174,829],{"class":467},[306,4176,562],{"class":463},[306,4178,834],{"class":552},[306,4180,556],{"class":463},[306,4182,679],{"class":467},[306,4184,574],{"class":463},[306,4186,4187],{"class":308,"line":668},[306,4188,360],{"class":463},[306,4190,4191],{"class":308,"line":685},[306,4192,1698],{"class":530},[306,4194,4195,4197,4199,4201,4203,4205],{"class":308,"line":697},[306,4196,1703],{"class":467},[306,4198,562],{"class":463},[306,4200,1708],{"class":467},[306,4202,545],{"class":544},[306,4204,802],{"class":467},[306,4206,488],{"class":463},[306,4208,4209],{"class":308,"line":712},[306,4210,525],{"emptyLinePlaceholder":10},[306,4212,4213],{"class":308,"line":728},[306,4214,1723],{"class":530},[306,4216,4217,4219,4221,4223,4225,4227,4229,4231,4233,4235,4237,4239,4241,4243,4245,4247],{"class":308,"line":734},[306,4218,1728],{"class":459},[306,4220,597],{"class":463},[306,4222,1027],{"class":467},[306,4224,562],{"class":463},[306,4226,970],{"class":467},[306,4228,954],{"class":544},[306,4230,802],{"class":467},[306,4232,562],{"class":463},[306,4234,989],{"class":467},[306,4236,562],{"class":463},[306,4238,994],{"class":467},[306,4240,997],{"class":544},[306,4242,478],{"class":477},[306,4244,1002],{"class":481},[306,4246,485],{"class":477},[306,4248,682],{"class":463},[306,4250,4251,4253,4255,4257,4259,4261,4263,4265,4267],{"class":308,"line":740},[306,4252,1763],{"class":459},[306,4254,1766],{"class":467},[306,4256,562],{"class":463},[306,4258,1771],{"class":552},[306,4260,556],{"class":463},[306,4262,1060],{"class":705},[306,4264,1778],{"class":463},[306,4266,5],{"class":552},[306,4268,694],{"class":463},[306,4270,4271,4273,4275,4277,4279,4281],{"class":308,"line":745},[306,4272,1787],{"class":467},[306,4274,652],{"class":651},[306,4276,478],{"class":477},[306,4278,1794],{"class":481},[306,4280,485],{"class":477},[306,4282,709],{"class":463},[306,4284,4285,4287,4289,4291,4293],{"class":308,"line":767},[306,4286,1803],{"class":467},[306,4288,652],{"class":651},[306,4290,478],{"class":477},[306,4292,1810],{"class":481},[306,4294,725],{"class":477},[306,4296,4297],{"class":308,"line":772},[306,4298,1817],{"class":463},[306,4300,4301],{"class":308,"line":778},[306,4302,1822],{"class":463},[306,4304,4305],{"class":308,"line":784},[306,4306,525],{"emptyLinePlaceholder":10},[306,4308,4309],{"class":308,"line":790},[306,4310,1831],{"class":530},[306,4312,4313,4315,4317,4319,4321,4323,4325,4327,4329,4331],{"class":308,"line":796},[306,4314,1728],{"class":459},[306,4316,597],{"class":463},[306,4318,1027],{"class":467},[306,4320,562],{"class":463},[306,4322,951],{"class":467},[306,4324,954],{"class":544},[306,4326,802],{"class":467},[306,4328,562],{"class":463},[306,4330,961],{"class":467},[306,4332,682],{"class":463},[306,4334,4335,4337,4339,4341,4343,4345],{"class":308,"line":807},[306,4336,1858],{"class":467},[306,4338,562],{"class":463},[306,4340,1863],{"class":467},[306,4342,545],{"class":544},[306,4344,656],{"class":655},[306,4346,488],{"class":463},[306,4348,4349],{"class":308,"line":815},[306,4350,1822],{"class":463},[306,4352,4353],{"class":308,"line":843},[306,4354,525],{"emptyLinePlaceholder":10},[306,4356,4357,4359],{"class":308,"line":859},[306,4358,1882],{"class":552},[306,4360,1885],{"class":463},[306,4362,4363,4365,4367,4369,4371],{"class":308,"line":885},[306,4364,846],{"class":463},[306,4366,849],{"class":459},[306,4368,597],{"class":463},[306,4370,867],{"class":467},[306,4372,682],{"class":463},[306,4374,4375,4377,4379,4381,4383,4385,4387,4389,4391,4393],{"class":308,"line":891},[306,4376,862],{"class":467},[306,4378,562],{"class":463},[306,4380,867],{"class":552},[306,4382,556],{"class":463},[306,4384,485],{"class":477},[306,4386,1912],{"class":481},[306,4388,485],{"class":477},[306,4390,500],{"class":463},[306,4392,867],{"class":467},[306,4394,574],{"class":463},[306,4396,4397],{"class":308,"line":921},[306,4398,1925],{"class":530},[306,4400,4401,4403],{"class":308,"line":926},[306,4402,1882],{"class":552},[306,4404,1885],{"class":463},[306,4406,4407],{"class":308,"line":931},[306,4408,737],{"class":463},[306,4410,4411],{"class":308,"line":937},[306,4412,1940],{"class":463},[306,4414,4415],{"class":308,"line":975},[306,4416,525],{"emptyLinePlaceholder":10},[306,4418,4419,4421,4423,4425,4427,4429],{"class":308,"line":1009},[306,4420,1950],{"class":1949},[306,4422,562],{"class":463},[306,4424,1955],{"class":1949},[306,4426,545],{"class":544},[306,4428,1613],{"class":467},[306,4430,488],{"class":463},[225,4432,1964],{},[296,4434,4435],{"className":1527,"code":1967,"filename":1968,"language":1530,"meta":301,"style":301},[303,4436,4437,4457,4473,4493,4497,4501,4539,4563,4567,4571,4585,4605,4619,4631,4635,4639,4643,4647,4665,4669,4673],{"__ignoreMap":301},[306,4438,4439,4441,4443,4445,4447,4449,4451,4453,4455],{"class":308,"line":309},[306,4440,537],{"class":536},[306,4442,1977],{"class":540},[306,4444,545],{"class":544},[306,4446,1548],{"class":552},[306,4448,556],{"class":463},[306,4450,485],{"class":477},[306,4452,1988],{"class":481},[306,4454,485],{"class":477},[306,4456,574],{"class":463},[306,4458,4459,4461,4463,4465,4467,4469,4471],{"class":308,"line":315},[306,4460,537],{"class":536},[306,4462,1999],{"class":540},[306,4464,545],{"class":544},[306,4466,1977],{"class":467},[306,4468,562],{"class":463},[306,4470,2008],{"class":552},[306,4472,1885],{"class":463},[306,4474,4475,4477,4479,4481,4483,4485,4487,4489,4491],{"class":308,"line":321},[306,4476,537],{"class":536},[306,4478,2017],{"class":540},[306,4480,545],{"class":544},[306,4482,1548],{"class":552},[306,4484,556],{"class":463},[306,4486,485],{"class":477},[306,4488,2028],{"class":481},[306,4490,485],{"class":477},[306,4492,574],{"class":463},[306,4494,4495],{"class":308,"line":327},[306,4496,525],{"emptyLinePlaceholder":10},[306,4498,4499],{"class":308,"line":333},[306,4500,2041],{"class":530},[306,4502,4503,4505,4507,4509,4511,4513,4515,4517,4519,4521,4523,4525,4527,4529,4531,4533,4535,4537],{"class":308,"line":339},[306,4504,2046],{"class":467},[306,4506,562],{"class":463},[306,4508,2051],{"class":552},[306,4510,556],{"class":463},[306,4512,485],{"class":477},[306,4514,2058],{"class":481},[306,4516,485],{"class":477},[306,4518,500],{"class":463},[306,4520,1708],{"class":467},[306,4522,500],{"class":463},[306,4524,594],{"class":536},[306,4526,597],{"class":463},[306,4528,1618],{"class":600},[306,4530,500],{"class":463},[306,4532,1623],{"class":600},[306,4534,604],{"class":463},[306,4536,607],{"class":536},[306,4538,610],{"class":463},[306,4540,4541,4543,4545,4547,4549,4551,4553,4555,4557,4559,4561],{"class":308,"line":345},[306,4542,630],{"class":536},[306,4544,464],{"class":463},[306,4546,907],{"class":540},[306,4548,500],{"class":463},[306,4550,916],{"class":540},[306,4552,471],{"class":463},[306,4554,1545],{"class":544},[306,4556,1646],{"class":467},[306,4558,562],{"class":463},[306,4560,902],{"class":467},[306,4562,488],{"class":463},[306,4564,4565],{"class":308,"line":351},[306,4566,525],{"emptyLinePlaceholder":10},[306,4568,4569],{"class":308,"line":357},[306,4570,2115],{"class":530},[306,4572,4573,4575,4577,4579,4581,4583],{"class":308,"line":363},[306,4574,671],{"class":459},[306,4576,597],{"class":463},[306,4578,1618],{"class":467},[306,4580,562],{"class":463},[306,4582,1863],{"class":467},[306,4584,682],{"class":463},[306,4586,4587,4589,4591,4593,4595,4597,4599,4601,4603],{"class":308,"line":369},[306,4588,894],{"class":459},[306,4590,1766],{"class":467},[306,4592,562],{"class":463},[306,4594,1771],{"class":552},[306,4596,556],{"class":463},[306,4598,1252],{"class":705},[306,4600,1778],{"class":463},[306,4602,5],{"class":552},[306,4604,694],{"class":463},[306,4606,4607,4609,4611,4613,4615,4617],{"class":308,"line":662},[306,4608,1076],{"class":467},[306,4610,652],{"class":651},[306,4612,478],{"class":477},[306,4614,2160],{"class":481},[306,4616,485],{"class":477},[306,4618,709],{"class":463},[306,4620,4621,4623,4625,4627,4629],{"class":308,"line":668},[306,4622,1094],{"class":467},[306,4624,652],{"class":651},[306,4626,478],{"class":477},[306,4628,2175],{"class":481},[306,4630,725],{"class":477},[306,4632,4633],{"class":308,"line":685},[306,4634,731],{"class":463},[306,4636,4637],{"class":308,"line":697},[306,4638,737],{"class":463},[306,4640,4641],{"class":308,"line":712},[306,4642,525],{"emptyLinePlaceholder":10},[306,4644,4645],{"class":308,"line":728},[306,4646,2194],{"class":530},[306,4648,4649,4651,4653,4655,4657,4659,4661,4663],{"class":308,"line":734},[306,4650,2199],{"class":467},[306,4652,562],{"class":463},[306,4654,5],{"class":552},[306,4656,2206],{"class":463},[306,4658,1385],{"class":467},[306,4660,652],{"class":651},[306,4662,656],{"class":655},[306,4664,659],{"class":463},[306,4666,4667],{"class":308,"line":740},[306,4668,1507],{"class":463},[306,4670,4671],{"class":308,"line":745},[306,4672,525],{"emptyLinePlaceholder":10},[306,4674,4675,4677,4679,4681,4683,4685],{"class":308,"line":767},[306,4676,1950],{"class":1949},[306,4678,562],{"class":463},[306,4680,1955],{"class":1949},[306,4682,545],{"class":544},[306,4684,1999],{"class":467},[306,4686,488],{"class":463},[246,4688,2240],{"id":2239},[225,4690,2243],{},[296,4692,4693],{"className":1527,"code":2246,"filename":2247,"language":1530,"meta":301,"style":301},[303,4694,4695,4703,4723,4745,4749,4753,4791,4803,4807,4811,4815,4843,4847,4853,4857,4883,4891,4915,4919,4923,4927,4941,4959,4963,4967,5001,5031,5041,5065,5069,5073,5077,5081,5099,5121,5151,5155,5159,5171,5175,5187,5191,5213,5217,5221,5233,5237],{"__ignoreMap":301},[306,4696,4697,4699,4701],{"class":308,"line":309},[306,4698,583],{"class":459},[306,4700,586],{"class":459},[306,4702,610],{"class":463},[306,4704,4705,4707,4709,4711,4713,4715,4717,4719,4721],{"class":308,"line":315},[306,4706,2262],{"class":536},[306,4708,2265],{"class":552},[306,4710,556],{"class":463},[306,4712,2270],{"class":600},[306,4714,500],{"class":463},[306,4716,565],{"class":600},[306,4718,500],{"class":463},[306,4720,2279],{"class":600},[306,4722,682],{"class":463},[306,4724,4725,4727,4729,4731,4733,4735,4737,4739,4741,4743],{"class":308,"line":321},[306,4726,1667],{"class":536},[306,4728,2288],{"class":540},[306,4730,545],{"class":544},[306,4732,549],{"class":548},[306,4734,2295],{"class":552},[306,4736,556],{"class":463},[306,4738,2270],{"class":467},[306,4740,562],{"class":463},[306,4742,2304],{"class":467},[306,4744,574],{"class":463},[306,4746,4747],{"class":308,"line":327},[306,4748,360],{"class":463},[306,4750,4751],{"class":308,"line":333},[306,4752,2315],{"class":530},[306,4754,4755,4757,4759,4761,4763,4765,4767,4769,4771,4773,4775,4777,4779,4781,4783,4785,4787,4789],{"class":308,"line":339},[306,4756,1728],{"class":459},[306,4758,597],{"class":463},[306,4760,2304],{"class":467},[306,4762,562],{"class":463},[306,4764,2328],{"class":467},[306,4766,2331],{"class":544},[306,4768,478],{"class":477},[306,4770,2336],{"class":481},[306,4772,485],{"class":477},[306,4774,2341],{"class":544},[306,4776,2288],{"class":467},[306,4778,562],{"class":463},[306,4780,2328],{"class":467},[306,4782,2331],{"class":544},[306,4784,478],{"class":477},[306,4786,2354],{"class":481},[306,4788,485],{"class":477},[306,4790,682],{"class":463},[306,4792,4793,4795,4797,4799,4801],{"class":308,"line":345},[306,4794,1763],{"class":459},[306,4796,2265],{"class":552},[306,4798,556],{"class":463},[306,4800,2270],{"class":467},[306,4802,574],{"class":463},[306,4804,4805],{"class":308,"line":351},[306,4806,1822],{"class":463},[306,4808,4809],{"class":308,"line":357},[306,4810,525],{"emptyLinePlaceholder":10},[306,4812,4813],{"class":308,"line":363},[306,4814,2383],{"class":530},[306,4816,4817,4819,4821,4823,4825,4827,4829,4831,4833,4835,4837,4839,4841],{"class":308,"line":369},[306,4818,1667],{"class":536},[306,4820,2390],{"class":540},[306,4822,545],{"class":544},[306,4824,2395],{"class":467},[306,4826,562],{"class":463},[306,4828,2400],{"class":467},[306,4830,562],{"class":463},[306,4832,2405],{"class":552},[306,4834,556],{"class":463},[306,4836,485],{"class":477},[306,4838,2412],{"class":481},[306,4840,485],{"class":477},[306,4842,574],{"class":463},[306,4844,4845],{"class":308,"line":662},[306,4846,525],{"emptyLinePlaceholder":10},[306,4848,4849,4851],{"class":308,"line":668},[306,4850,2425],{"class":459},[306,4852,610],{"class":463},[306,4854,4855],{"class":308,"line":685},[306,4856,2432],{"class":530},[306,4858,4859,4861,4863,4865,4867,4869,4871,4873,4875,4877,4879,4881],{"class":308,"line":697},[306,4860,2437],{"class":536},[306,4862,2440],{"class":540},[306,4864,545],{"class":544},[306,4866,755],{"class":459},[306,4868,2265],{"class":552},[306,4870,556],{"class":463},[306,4872,2451],{"class":481},[306,4874,2454],{"class":536},[306,4876,2457],{"class":467},[306,4878,2460],{"class":536},[306,4880,2463],{"class":481},[306,4882,2466],{"class":463},[306,4884,4885,4887,4889],{"class":308,"line":712},[306,4886,2471],{"class":467},[306,4888,652],{"class":651},[306,4890,610],{"class":463},[306,4892,4893,4895,4897,4899,4901,4903,4905,4907,4909,4911,4913],{"class":308,"line":728},[306,4894,2480],{"class":477},[306,4896,2483],{"class":481},[306,4898,485],{"class":477},[306,4900,652],{"class":651},[306,4902,2490],{"class":481},[306,4904,2454],{"class":536},[306,4906,565],{"class":467},[306,4908,562],{"class":2497},[306,4910,571],{"class":570},[306,4912,2460],{"class":536},[306,4914,2504],{"class":481},[306,4916,4917],{"class":308,"line":734},[306,4918,2509],{"class":463},[306,4920,4921],{"class":308,"line":740},[306,4922,1817],{"class":463},[306,4924,4925],{"class":308,"line":745},[306,4926,525],{"emptyLinePlaceholder":10},[306,4928,4929,4931,4933,4935,4937,4939],{"class":308,"line":767},[306,4930,2522],{"class":459},[306,4932,597],{"class":463},[306,4934,2527],{"class":467},[306,4936,562],{"class":463},[306,4938,2532],{"class":467},[306,4940,682],{"class":463},[306,4942,4943,4945,4947,4949,4951,4953,4955,4957],{"class":308,"line":772},[306,4944,2539],{"class":536},[306,4946,802],{"class":540},[306,4948,545],{"class":544},[306,4950,755],{"class":459},[306,4952,2440],{"class":467},[306,4954,562],{"class":463},[306,4956,5],{"class":552},[306,4958,1885],{"class":463},[306,4960,4961],{"class":308,"line":778},[306,4962,525],{"emptyLinePlaceholder":10},[306,4964,4965],{"class":308,"line":784},[306,4966,2562],{"class":530},[306,4968,4969,4971,4973,4975,4977,4979,4981,4983,4985,4987,4989,4991,4993,4995,4997,4999],{"class":308,"line":790},[306,4970,2567],{"class":459},[306,4972,597],{"class":463},[306,4974,1027],{"class":467},[306,4976,562],{"class":463},[306,4978,970],{"class":467},[306,4980,954],{"class":544},[306,4982,802],{"class":467},[306,4984,562],{"class":463},[306,4986,989],{"class":467},[306,4988,562],{"class":463},[306,4990,994],{"class":467},[306,4992,997],{"class":544},[306,4994,478],{"class":477},[306,4996,1002],{"class":481},[306,4998,485],{"class":477},[306,5000,682],{"class":463},[306,5002,5003,5005,5007,5009,5011,5013,5015,5017,5019,5021,5023,5025,5027,5029],{"class":308,"line":796},[306,5004,2602],{"class":459},[306,5006,549],{"class":548},[306,5008,2607],{"class":552},[306,5010,556],{"class":463},[306,5012,2612],{"class":570},[306,5014,562],{"class":463},[306,5016,2617],{"class":552},[306,5018,2206],{"class":463},[306,5020,867],{"class":467},[306,5022,652],{"class":651},[306,5024,478],{"class":477},[306,5026,2628],{"class":481},[306,5028,485],{"class":477},[306,5030,2633],{"class":463},[306,5032,5033,5035,5037,5039],{"class":308,"line":807},[306,5034,2638],{"class":467},[306,5036,652],{"class":651},[306,5038,2643],{"class":705},[306,5040,709],{"class":463},[306,5042,5043,5045,5047,5049,5051,5053,5055,5057,5059,5061,5063],{"class":308,"line":815},[306,5044,2650],{"class":467},[306,5046,652],{"class":651},[306,5048,464],{"class":463},[306,5050,485],{"class":477},[306,5052,2659],{"class":481},[306,5054,485],{"class":477},[306,5056,652],{"class":651},[306,5058,478],{"class":477},[306,5060,2668],{"class":481},[306,5062,485],{"class":477},[306,5064,2673],{"class":463},[306,5066,5067],{"class":308,"line":843},[306,5068,2678],{"class":463},[306,5070,5071],{"class":308,"line":859},[306,5072,2509],{"class":463},[306,5074,5075],{"class":308,"line":885},[306,5076,2687],{"class":463},[306,5078,5079],{"class":308,"line":891},[306,5080,2692],{"class":530},[306,5082,5083,5085,5087,5089,5091,5093,5095,5097],{"class":308,"line":921},[306,5084,2539],{"class":536},[306,5086,2699],{"class":540},[306,5088,545],{"class":544},[306,5090,549],{"class":548},[306,5092,2706],{"class":552},[306,5094,556],{"class":463},[306,5096,2270],{"class":467},[306,5098,574],{"class":463},[306,5100,5101,5103,5105,5107,5109,5111,5113,5115,5117,5119],{"class":308,"line":926},[306,5102,2567],{"class":459},[306,5104,597],{"class":463},[306,5106,1027],{"class":467},[306,5108,562],{"class":463},[306,5110,951],{"class":467},[306,5112,954],{"class":544},[306,5114,802],{"class":467},[306,5116,562],{"class":463},[306,5118,961],{"class":467},[306,5120,682],{"class":463},[306,5122,5123,5125,5127,5129,5131,5133,5135,5137,5139,5141,5143,5145,5147,5149],{"class":308,"line":931},[306,5124,2739],{"class":467},[306,5126,562],{"class":463},[306,5128,2400],{"class":467},[306,5130,562],{"class":463},[306,5132,2748],{"class":552},[306,5134,556],{"class":463},[306,5136,485],{"class":477},[306,5138,2755],{"class":481},[306,5140,485],{"class":477},[306,5142,500],{"class":463},[306,5144,485],{"class":477},[306,5146,2764],{"class":481},[306,5148,485],{"class":477},[306,5150,574],{"class":463},[306,5152,5153],{"class":308,"line":937},[306,5154,2509],{"class":463},[306,5156,5157],{"class":308,"line":975},[306,5158,2687],{"class":463},[306,5160,5161,5163,5165,5167,5169],{"class":308,"line":1009},[306,5162,2781],{"class":459},[306,5164,2265],{"class":552},[306,5166,556],{"class":463},[306,5168,2788],{"class":467},[306,5170,574],{"class":463},[306,5172,5173],{"class":308,"line":1014},[306,5174,2795],{"class":463},[306,5176,5177,5179,5181,5183,5185],{"class":308,"line":1020},[306,5178,2800],{"class":463},[306,5180,849],{"class":459},[306,5182,597],{"class":463},[306,5184,854],{"class":467},[306,5186,682],{"class":463},[306,5188,5189],{"class":308,"line":1036},[306,5190,2813],{"class":530},[306,5192,5193,5195,5197,5199,5201,5203,5205,5207,5209,5211],{"class":308,"line":1042},[306,5194,2818],{"class":467},[306,5196,562],{"class":463},[306,5198,867],{"class":552},[306,5200,556],{"class":463},[306,5202,485],{"class":477},[306,5204,2829],{"class":481},[306,5206,485],{"class":477},[306,5208,500],{"class":463},[306,5210,854],{"class":467},[306,5212,574],{"class":463},[306,5214,5215],{"class":308,"line":1048},[306,5216,1822],{"class":463},[306,5218,5219],{"class":308,"line":1065},[306,5220,525],{"emptyLinePlaceholder":10},[306,5222,5223,5225,5227,5229,5231],{"class":308,"line":1073},[306,5224,894],{"class":459},[306,5226,2265],{"class":552},[306,5228,556],{"class":463},[306,5230,2270],{"class":467},[306,5232,574],{"class":463},[306,5234,5235],{"class":308,"line":1091},[306,5236,737],{"class":463},[306,5238,5239],{"class":308,"line":1109},[306,5240,2866],{"class":463},[2868,5242,5243],{},[225,5244,2872],{},[238,5246,2876],{"id":2875},[225,5248,2879,5249,2883],{},[303,5250,2882],{},[225,5252,2886,5253,2890,5255,2893],{},[303,5254,2889],{},[303,5256,2882],{},[246,5258,2897],{"id":2896},[254,5260,5261,5269],{},[257,5262,5263,2905,5265,2909,5267,2913],{},[260,5264,2904],{},[303,5266,2908],{},[303,5268,2912],{},[257,5270,5271,2919,5273,2922],{},[260,5272,2918],{},[303,5274,2882],{},[225,5276,2925,5277,2929,5279,2933],{},[303,5278,2928],{},[303,5280,2932],{},[238,5282,2937],{"id":2936},[225,5284,2940],{},[246,5286,2944],{"id":2943},[225,5288,2947],{},[225,5290,2950],{},[246,5292,2954],{"id":2953},[225,5294,2957],{},[225,5296,2960],{},[238,5298,2964],{"id":2963},[225,5300,2967],{},[225,5302,2970],{},[296,5304,5305],{"className":2973,"code":2974,"language":2975,"meta":301,"style":301},[303,5306,5307,5311,5315,5319],{"__ignoreMap":301},[306,5308,5309],{"class":308,"line":309},[306,5310,2982],{},[306,5312,5313],{"class":308,"line":315},[306,5314,2987],{},[306,5316,5317],{"class":308,"line":321},[306,5318,2992],{},[306,5320,5321],{"class":308,"line":327},[306,5322,2997],{},[225,5324,3000],{},[238,5326,3004],{"id":3003},[225,5328,3007],{},[225,5330,3010],{},[225,5332,3013],{},[3015,5334,3017],{},{"title":301,"searchDepth":315,"depth":315,"links":5336},[5337,5341,5346,5349,5354,5357,5361,5362],{"id":240,"depth":315,"text":241,"children":5338},[5339,5340],{"id":248,"depth":321,"text":249},{"id":284,"depth":321,"text":285},{"id":375,"depth":315,"text":376,"children":5342},[5343,5344,5345],{"id":382,"depth":321,"text":383},{"id":389,"depth":321,"text":390},{"id":396,"depth":321,"text":397},{"id":409,"depth":315,"text":410,"children":5347},[5348],{"id":419,"depth":321,"text":420},{"id":432,"depth":315,"text":433,"children":5350},[5351,5352,5353],{"id":439,"depth":321,"text":440},{"id":1520,"depth":321,"text":1521},{"id":2239,"depth":321,"text":2240},{"id":2875,"depth":315,"text":2876,"children":5355},[5356],{"id":2896,"depth":321,"text":2897},{"id":2936,"depth":315,"text":2937,"children":5358},[5359,5360],{"id":2943,"depth":321,"text":2944},{"id":2953,"depth":321,"text":2954},{"id":2963,"depth":315,"text":2964},{"id":3003,"depth":315,"text":3004},{},{"title":129,"description":3047},[3056,3057,3058,3059,3060],1782044516065]