nord_proxy/
lib.rs

1//! # nord-proxy
2//!
3//! `nord-proxy` is a Rust crate for retrieving NordVPN proxy endpoints (SOCKS5 and HTTP/HTTPS)
4//! and integrating them with `reqwest`.
5//!
6//! ## Usage
7//!
8//! ```rust
9//! use nord_proxy::{Proxy, Socks5, ProxyTrait};
10//!
11//! // SOCKS5 proxies
12//! let socks5 = Socks5::new().await;
13//! let socks5_proxies = socks5.proxies("username", "password");
14//!
15//! // HTTP / HTTPS proxies
16//! let proxy = Proxy::new().await;
17//! let http_proxies = proxy.proxies("username", "password");
18//!
19//! // Example: use with reqwest
20//! let proxy_info = &http_proxies[0];
21//! let client = reqwest::Client::builder()
22//!     .proxy(reqwest::Proxy::all(proxy_info.url())?)
23//!     .build()?;
24//! ```
25use serde::{Deserialize, Serialize};
26
27use crate::structure::{Root, Technologies};
28
29mod structure;
30
31async fn get_info(s: &str) -> Vec<Root> {
32    let client = reqwest::Client::new();
33    let response = client.get(s).send().await.unwrap();
34    let json: Vec<Root> = response.json().await.unwrap();
35    json
36}
37
38pub struct Socks5 {
39    data: Vec<Root>,
40}
41
42pub struct Proxy {
43    data: Vec<(u32, Country, City, Technologies)>,
44}
45
46impl Proxy {
47    pub async fn new() -> Self {
48        let url = "https://api.nordvpn.com/v1/servers?filters[servers_services][identifier]=proxy&limit=0";
49        Proxy {
50            data: get_info(url)
51                .await
52                .into_iter()
53                .filter(|v| {
54                    v.status.to_lowercase() == "online"
55                        && v.services.iter().any(|v| v.identifier == "proxy")
56                })
57                .flat_map(|v| {
58                    v.technologies
59                        .into_iter()
60                        .filter(|v| v.identifier == "proxy_ssl")
61                        .map(|vv| {
62                            (
63                                v.load,
64                                v.locations.first().unwrap().country.code.clone(),
65                                v.locations.first().unwrap().country.city.name.clone(),
66                                vv,
67                            )
68                        })
69                        .collect::<Vec<_>>()
70                })
71                .collect(),
72        }
73    }
74}
75
76impl ProxyTrait for Proxy {
77    fn proxies(&self, username: &str, password: &str) -> Vec<ProxyInfo> {
78        self.data
79            .iter()
80            .map(|v| ProxyInfo {
81                load: v.0,
82                country: v.1,
83                city: v.2,
84                proxy: reqwest::Proxy::https(format!(
85                    "https://{}:89",
86                    v.3.metadata
87                        .iter()
88                        .find(|v| v.name == "proxy_hostname")
89                        .unwrap()
90                        .value
91                ))
92                .unwrap()
93                .basic_auth(username, password),
94            })
95            .collect()
96    }
97}
98impl Socks5 {
99    pub async fn new() -> Self {
100        let url = "https://api.nordvpn.com/v1/servers?filters[servers_technologies][identifier]=socks&limit=0";
101        Socks5 {
102            data: get_info(url)
103                .await
104                .into_iter()
105                .filter(|v| {
106                    v.status == "online"
107                        && v.technologies
108                            .iter()
109                            .any(|v| v.pivot.status == "online" && v.identifier == "socks")
110                })
111                .collect(),
112        }
113    }
114}
115
116impl ProxyTrait for Socks5 {
117    fn proxies(&self, username: &str, password: &str) -> Vec<ProxyInfo> {
118        self.data
119            .iter()
120            .map(|v| {
121                let c = v.locations.first().unwrap();
122                ProxyInfo {
123                    load: v.load,
124                    city: c.country.city.name,
125                    country: c.country.code,
126                    proxy: reqwest::Proxy::all(format!(
127                        "socks5h://{username}:{password}@{}:1080",
128                        v.hostname
129                    ))
130                    .unwrap(),
131                }
132            })
133            .collect()
134    }
135}
136
137pub trait ProxyTrait {
138    fn proxies(&self, username: &str, password: &str) -> Vec<ProxyInfo>;
139}
140
141pub struct ProxyInfo {
142    pub load: u32,
143    pub country: Country,
144    pub city: City,
145    pub proxy: reqwest::Proxy,
146}
147
148#[cfg(test)]
149mod tests {
150    use crate::{Proxy, ProxyTrait, Socks5};
151
152    #[tokio::test]
153    async fn proxy() {
154        let proxy = Proxy::new().await.proxies("user", "pass");
155
156        assert!(proxy.len() > 0)
157    }
158
159    #[tokio::test]
160    async fn socks() {
161        let proxy = Socks5::new().await.proxies("user", "pass");
162        assert!(proxy.len() > 0)
163    }
164}
165
166#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
167pub enum Country {
168    #[serde(rename = "EE")]
169    EE,
170    #[serde(rename = "NP")]
171    NP,
172    #[serde(rename = "ZA")]
173    ZA,
174    #[serde(rename = "QA")]
175    QA,
176    #[serde(rename = "GB")]
177    GB,
178    #[serde(rename = "JO")]
179    JO,
180    #[serde(rename = "SV")]
181    SV,
182    #[serde(rename = "LU")]
183    LU,
184    #[serde(rename = "TT")]
185    TT,
186    #[serde(rename = "LB")]
187    LB,
188    #[serde(rename = "AZ")]
189    AZ,
190    #[serde(rename = "BH")]
191    BH,
192    #[serde(rename = "LT")]
193    LT,
194    #[serde(rename = "PL")]
195    PL,
196    #[serde(rename = "PG")]
197    PG,
198    #[serde(rename = "LY")]
199    LY,
200    #[serde(rename = "HK")]
201    HK,
202    #[serde(rename = "IN")]
203    IN,
204    #[serde(rename = "TH")]
205    TH,
206    #[serde(rename = "CY")]
207    CY,
208    #[serde(rename = "UA")]
209    UA,
210    #[serde(rename = "KY")]
211    KY,
212    #[serde(rename = "FR")]
213    FR,
214    #[serde(rename = "KM")]
215    KM,
216    #[serde(rename = "MC")]
217    MC,
218    #[serde(rename = "NL")]
219    NL,
220    #[serde(rename = "AD")]
221    AD,
222    #[serde(rename = "MM")]
223    MM,
224    #[serde(rename = "PK")]
225    PK,
226    #[serde(rename = "ME")]
227    ME,
228    #[serde(rename = "DZ")]
229    DZ,
230    #[serde(rename = "TW")]
231    TW,
232    #[serde(rename = "BT")]
233    BT,
234    #[serde(rename = "UZ")]
235    UZ,
236    #[serde(rename = "MN")]
237    MN,
238    #[serde(rename = "LI")]
239    LI,
240    #[serde(rename = "MX")]
241    MX,
242    #[serde(rename = "JM")]
243    JM,
244    #[serde(rename = "GH")]
245    GH,
246    #[serde(rename = "BG")]
247    BG,
248    #[serde(rename = "RS")]
249    RS,
250    #[serde(rename = "BO")]
251    BO,
252    #[serde(rename = "BE")]
253    BE,
254    #[serde(rename = "GR")]
255    GR,
256    #[serde(rename = "LV")]
257    LV,
258    #[serde(rename = "SN")]
259    SN,
260    #[serde(rename = "PA")]
261    PA,
262    #[serde(rename = "TJ")]
263    TJ,
264    #[serde(rename = "BR")]
265    BR,
266    #[serde(rename = "KH")]
267    KH,
268    #[serde(rename = "AF")]
269    AF,
270    #[serde(rename = "KR")]
271    KR,
272    #[serde(rename = "BZ")]
273    BZ,
274    #[serde(rename = "ES")]
275    ES,
276    #[serde(rename = "HU")]
277    HU,
278    #[serde(rename = "AR")]
279    AR,
280    #[serde(rename = "LA")]
281    LA,
282    #[serde(rename = "SK")]
283    SK,
284    #[serde(rename = "MK")]
285    MK,
286    #[serde(rename = "TR")]
287    TR,
288    #[serde(rename = "CO")]
289    CO,
290    #[serde(rename = "SE")]
291    SE,
292    #[serde(rename = "CA")]
293    CA,
294    #[serde(rename = "AO")]
295    AO,
296    #[serde(rename = "TN")]
297    TN,
298    #[serde(rename = "KW")]
299    KW,
300    #[serde(rename = "KE")]
301    KE,
302    #[serde(rename = "DE")]
303    DE,
304    #[serde(rename = "CR")]
305    CR,
306    #[serde(rename = "NO")]
307    NO,
308    #[serde(rename = "DO")]
309    DO,
310    #[serde(rename = "HR")]
311    HR,
312    #[serde(rename = "MR")]
313    MR,
314    #[serde(rename = "GT")]
315    GT,
316    #[serde(rename = "AM")]
317    AM,
318    #[serde(rename = "MA")]
319    MA,
320    #[serde(rename = "IL")]
321    IL,
322    #[serde(rename = "BN")]
323    BN,
324    #[serde(rename = "BA")]
325    BA,
326    #[serde(rename = "BS")]
327    BS,
328    #[serde(rename = "EC")]
329    EC,
330    #[serde(rename = "NZ")]
331    NZ,
332    #[serde(rename = "IT")]
333    IT,
334    #[serde(rename = "MD")]
335    MD,
336    #[serde(rename = "CH")]
337    CH,
338    #[serde(rename = "SO")]
339    SO,
340    #[serde(rename = "EG")]
341    EG,
342    #[serde(rename = "JP")]
343    JP,
344    #[serde(rename = "VN")]
345    VN,
346    #[serde(rename = "AE")]
347    AE,
348    #[serde(rename = "JE")]
349    JE,
350    #[serde(rename = "RO")]
351    RO,
352    #[serde(rename = "KZ")]
353    KZ,
354    #[serde(rename = "DK")]
355    DK,
356    #[serde(rename = "US")]
357    US,
358    #[serde(rename = "IQ")]
359    IQ,
360    #[serde(rename = "LK")]
361    LK,
362    #[serde(rename = "AU")]
363    AU,
364    #[serde(rename = "PH")]
365    PH,
366    #[serde(rename = "MZ")]
367    MZ,
368    #[serde(rename = "PY")]
369    PY,
370    #[serde(rename = "GE")]
371    GE,
372    #[serde(rename = "PR")]
373    PR,
374    #[serde(rename = "NG")]
375    NG,
376    #[serde(rename = "ID")]
377    ID,
378    #[serde(rename = "VE")]
379    VE,
380    #[serde(rename = "MU")]
381    MU,
382    #[serde(rename = "PT")]
383    PT,
384    #[serde(rename = "UY")]
385    UY,
386    #[serde(rename = "IM")]
387    IM,
388    #[serde(rename = "CZ")]
389    CZ,
390    #[serde(rename = "CL")]
391    CL,
392    #[serde(rename = "MT")]
393    MT,
394    #[serde(rename = "MY")]
395    MY,
396    #[serde(rename = "RW")]
397    RW,
398    #[serde(rename = "AT")]
399    AT,
400    #[serde(rename = "FI")]
401    FI,
402    #[serde(rename = "ET")]
403    ET,
404    #[serde(rename = "AL")]
405    AL,
406    #[serde(rename = "BD")]
407    BD,
408    #[serde(rename = "IE")]
409    IE,
410    #[serde(rename = "GU")]
411    GU,
412    #[serde(rename = "SI")]
413    SI,
414    #[serde(rename = "SG")]
415    SG,
416    #[serde(rename = "HN")]
417    HN,
418    #[serde(rename = "BM")]
419    BM,
420    #[serde(rename = "PE")]
421    PE,
422    #[serde(rename = "GL")]
423    GL,
424    #[serde(rename = "IS")]
425    IS,
426}
427
428#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
429pub enum City {
430    #[serde(rename = "Sofia")]
431    Sofia,
432    #[serde(rename = "Jakarta")]
433    Jakarta,
434    #[serde(rename = "Guatemala City")]
435    GuatemalaCity,
436    #[serde(rename = "Kuala Lumpur")]
437    KualaLumpur,
438    #[serde(rename = "Wilmington")]
439    Wilmington,
440    #[serde(rename = "Dublin")]
441    Dublin,
442    #[serde(rename = "Warsaw")]
443    Warsaw,
444    #[serde(rename = "Dushanbe")]
445    Dushanbe,
446    #[serde(rename = "Chicago")]
447    Chicago,
448    #[serde(rename = "Brisbane")]
449    Brisbane,
450    #[serde(rename = "Thimphu")]
451    Thimphu,
452    #[serde(rename = "Luxembourg")]
453    Luxembourg,
454    #[serde(rename = "Houston")]
455    Houston,
456    #[serde(rename = "Buenos Aires")]
457    BuenosAires,
458    #[serde(rename = "Baltimore")]
459    Baltimore,
460    #[serde(rename = "San Salvador")]
461    SanSalvador,
462    #[serde(rename = "Istanbul")]
463    Istanbul,
464    #[serde(rename = "Huntington")]
465    Huntington,
466    #[serde(rename = "Nuuk")]
467    Nuuk,
468    #[serde(rename = "Quito")]
469    Quito,
470    #[serde(rename = "Vancouver")]
471    Vancouver,
472    #[serde(rename = "Dakar")]
473    Dakar,
474    #[serde(rename = "Montevideo")]
475    Montevideo,
476    #[serde(rename = "Sarajevo")]
477    Sarajevo,
478    #[serde(rename = "Algiers")]
479    Algiers,
480    #[serde(rename = "Mexico")]
481    Mexico,
482    #[serde(rename = "Doha")]
483    Doha,
484    #[serde(rename = "Los Angeles")]
485    LosAngeles,
486    #[serde(rename = "Riga")]
487    Riga,
488    #[serde(rename = "Kigali")]
489    Kigali,
490    #[serde(rename = "Oslo")]
491    Oslo,
492    #[serde(rename = "Taipei")]
493    Taipei,
494    #[serde(rename = "Port Louis")]
495    PortLouis,
496    #[serde(rename = "Auckland")]
497    Auckland,
498    #[serde(rename = "Port of Spain")]
499    PortOfSpain,
500    #[serde(rename = "Panama City")]
501    PanamaCity,
502    #[serde(rename = "La Paz")]
503    LaPaz,
504    #[serde(rename = "George Town")]
505    GeorgeTown,
506    #[serde(rename = "London")]
507    London,
508    #[serde(rename = "Tokyo")]
509    Tokyo,
510    #[serde(rename = "Phoenix")]
511    Phoenix,
512    #[serde(rename = "San Jose")]
513    SanJose,
514    #[serde(rename = "Zagreb")]
515    Zagreb,
516    #[serde(rename = "Buffalo")]
517    Buffalo,
518    #[serde(rename = "Marseille")]
519    Marseille,
520    #[serde(rename = "Santiago")]
521    Santiago,
522    #[serde(rename = "Yerevan")]
523    Yerevan,
524    #[serde(rename = "Kingston")]
525    Kingston,
526    #[serde(rename = "Ashburn")]
527    Ashburn,
528    #[serde(rename = "Lima")]
529    Lima,
530    #[serde(rename = "Milan")]
531    Milan,
532    #[serde(rename = "Tripoli")]
533    Tripoli,
534    #[serde(rename = "Dhaka")]
535    Dhaka,
536    #[serde(rename = "Stockholm")]
537    Stockholm,
538    #[serde(rename = "Addis Ababa")]
539    AddisAbaba,
540    #[serde(rename = "Omaha")]
541    Omaha,
542    #[serde(rename = "Toronto")]
543    Toronto,
544    #[serde(rename = "Berlin")]
545    Berlin,
546    #[serde(rename = "Burlington")]
547    Burlington,
548    #[serde(rename = "Charlotte")]
549    Charlotte,
550    #[serde(rename = "Hagatna")]
551    Hagatna,
552    #[serde(rename = "Belgrade")]
553    Belgrade,
554    #[serde(rename = "Paris")]
555    Paris,
556    #[serde(rename = "Athens")]
557    Athens,
558    #[serde(rename = "Luanda")]
559    Luanda,
560    #[serde(rename = "Providence")]
561    Providence,
562    #[serde(rename = "Lewiston")]
563    Lewiston,
564    #[serde(rename = "Tegucigalpa")]
565    Tegucigalpa,
566    #[serde(rename = "Denver")]
567    Denver,
568    #[serde(rename = "Sao Paulo")]
569    SaoPaulo,
570    #[serde(rename = "Osaka")]
571    Osaka,
572    #[serde(rename = "Maputo")]
573    Maputo,
574    #[serde(rename = "Kyiv")]
575    Kyiv,
576    #[serde(rename = "Ho Chi Minh City")]
577    HoChiMinhCity,
578    #[serde(rename = "Phnom Penh")]
579    PhnomPenh,
580    #[serde(rename = "Karachi")]
581    Karachi,
582    #[serde(rename = "Accra")]
583    Accra,
584    #[serde(rename = "Glasgow")]
585    Glasgow,
586    #[serde(rename = "Dubai")]
587    Dubai,
588    #[serde(rename = "Chisinau")]
589    Chisinau,
590    #[serde(rename = "Baku")]
591    Baku,
592    #[serde(rename = "Perth")]
593    Perth,
594    #[serde(rename = "Palermo")]
595    Palermo,
596    #[serde(rename = "McAllen")]
597    McAllen,
598    #[serde(rename = "Madrid")]
599    Madrid,
600    #[serde(rename = "Douglas")]
601    Douglas,
602    #[serde(rename = "Pittsburgh")]
603    Pittsburgh,
604    #[serde(rename = "Edinburgh")]
605    Edinburgh,
606    #[serde(rename = "Lagos")]
607    Lagos,
608    #[serde(rename = "Ljubljana")]
609    Ljubljana,
610    #[serde(rename = "Lisbon")]
611    Lisbon,
612    #[serde(rename = "Caracas")]
613    Caracas,
614    #[serde(rename = "Prague")]
615    Prague,
616    #[serde(rename = "Beirut")]
617    Beirut,
618    #[serde(rename = "Vientiane")]
619    Vientiane,
620    #[serde(rename = "Copenhagen")]
621    Copenhagen,
622    #[serde(rename = "Cairo")]
623    Cairo,
624    #[serde(rename = "Sydney")]
625    Sydney,
626    #[serde(rename = "Nouakchott")]
627    Nouakchott,
628    #[serde(rename = "Rome")]
629    Rome,
630    #[serde(rename = "Boston")]
631    Boston,
632    #[serde(rename = "Bangkok")]
633    Bangkok,
634    #[serde(rename = "New Haven")]
635    NewHaven,
636    #[serde(rename = "Astana")]
637    Astana,
638    #[serde(rename = "Valletta")]
639    Valletta,
640    #[serde(rename = "Mumbai")]
641    Mumbai,
642    #[serde(rename = "Bandar Seri Begawan")]
643    BandarSeriBegawan,
644    #[serde(rename = "Skopje")]
645    Skopje,
646    #[serde(rename = "Kathmandu")]
647    Kathmandu,
648    #[serde(rename = "Tbilisi")]
649    Tbilisi,
650    #[serde(rename = "Zurich")]
651    Zurich,
652    #[serde(rename = "Hong Kong")]
653    HongKong,
654    #[serde(rename = "Belmopan")]
655    Belmopan,
656    #[serde(rename = "Mogadishu")]
657    Mogadishu,
658    #[serde(rename = "Barcelona")]
659    Barcelona,
660    #[serde(rename = "Moroni")]
661    Moroni,
662    #[serde(rename = "New York")]
663    NewYork,
664    #[serde(rename = "Nashua")]
665    Nashua,
666    #[serde(rename = "Reykjavik")]
667    Reykjavik,
668    #[serde(rename = "San Juan")]
669    SanJuan,
670    #[serde(rename = "Johannesburg")]
671    Johannesburg,
672    #[serde(rename = "Amman")]
673    Amman,
674    #[serde(rename = "Nicosia")]
675    Nicosia,
676    #[serde(rename = "Nairobi")]
677    Nairobi,
678    #[serde(rename = "Colombo")]
679    Colombo,
680    #[serde(rename = "Tashkent")]
681    Tashkent,
682    #[serde(rename = "Miami")]
683    Miami,
684    #[serde(rename = "Rabat")]
685    Rabat,
686    #[serde(rename = "Hamilton")]
687    Hamilton,
688    #[serde(rename = "Saint Louis")]
689    SaintLouis,
690    #[serde(rename = "Atlanta")]
691    Atlanta,
692    #[serde(rename = "Montreal")]
693    Montreal,
694    #[serde(rename = "Tel Aviv")]
695    TelAviv,
696    #[serde(rename = "Ulaanbaatar")]
697    Ulaanbaatar,
698    #[serde(rename = "Port Moresby")]
699    PortMoresby,
700    #[serde(rename = "Seoul")]
701    Seoul,
702    #[serde(rename = "Nassau")]
703    Nassau,
704    #[serde(rename = "Salt Lake City")]
705    SaltLakeCity,
706    #[serde(rename = "Hamburg")]
707    Hamburg,
708    #[serde(rename = "San Francisco")]
709    SanFrancisco,
710    #[serde(rename = "Bucharest")]
711    Bucharest,
712    #[serde(rename = "Andorra la Vella")]
713    AndorraLaVella,
714    #[serde(rename = "Melbourne")]
715    Melbourne,
716    #[serde(rename = "Kuwait City")]
717    KuwaitCity,
718    #[serde(rename = "Helsinki")]
719    Helsinki,
720    #[serde(rename = "Nashville")]
721    Nashville,
722    #[serde(rename = "Saint Helier")]
723    SaintHelier,
724    #[serde(rename = "Brussels")]
725    Brussels,
726    #[serde(rename = "Dallas")]
727    Dallas,
728    #[serde(rename = "Budapest")]
729    Budapest,
730    #[serde(rename = "Monte Carlo")]
731    MonteCarlo,
732    #[serde(rename = "Bogota")]
733    Bogota,
734    #[serde(rename = "Vilnius")]
735    Vilnius,
736    #[serde(rename = "Tunis")]
737    Tunis,
738    #[serde(rename = "Amsterdam")]
739    Amsterdam,
740    #[serde(rename = "Tirana")]
741    Tirana,
742    #[serde(rename = "Podgorica")]
743    Podgorica,
744    #[serde(rename = "Fujairah")]
745    Fujairah,
746    #[serde(rename = "Vienna")]
747    Vienna,
748    #[serde(rename = "Bratislava")]
749    Bratislava,
750    #[serde(rename = "Seattle")]
751    Seattle,
752    #[serde(rename = "Baghdad")]
753    Baghdad,
754    #[serde(rename = "Frankfurt")]
755    Frankfurt,
756    #[serde(rename = "Manchester")]
757    Manchester,
758    #[serde(rename = "Trenton")]
759    Trenton,
760    #[serde(rename = "Asuncion")]
761    Asuncion,
762    #[serde(rename = "Singapore")]
763    Singapore,
764    #[serde(rename = "Vaduz")]
765    Vaduz,
766    #[serde(rename = "Adelaide")]
767    Adelaide,
768    #[serde(rename = "Hanoi")]
769    Hanoi,
770    #[serde(rename = "Tallinn")]
771    Tallinn,
772    #[serde(rename = "Santo Domingo")]
773    SantoDomingo,
774    #[serde(rename = "Manama")]
775    Manama,
776    #[serde(rename = "Kansas City")]
777    KansasCity,
778    #[serde(rename = "Kabul")]
779    Kabul,
780    #[serde(rename = "Naypyidaw")]
781    Naypyidaw,
782    #[serde(rename = "Manila")]
783    Manila,
784    #[serde(rename = "Strasbourg")]
785    Strasbourg,
786}