Skip to main content

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    #[serde(rename = "SR")]
427    SR,
428}
429
430#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
431pub enum City {
432    #[serde(rename = "Sofia")]
433    Sofia,
434    #[serde(rename = "Jakarta")]
435    Jakarta,
436    #[serde(rename = "Guatemala City")]
437    GuatemalaCity,
438    #[serde(rename = "Kuala Lumpur")]
439    KualaLumpur,
440    #[serde(rename = "Wilmington")]
441    Wilmington,
442    #[serde(rename = "Dublin")]
443    Dublin,
444    #[serde(rename = "Warsaw")]
445    Warsaw,
446    #[serde(rename = "Dushanbe")]
447    Dushanbe,
448    #[serde(rename = "Chicago")]
449    Chicago,
450    #[serde(rename = "Brisbane")]
451    Brisbane,
452    #[serde(rename = "Thimphu")]
453    Thimphu,
454    #[serde(rename = "Luxembourg")]
455    Luxembourg,
456    #[serde(rename = "Houston")]
457    Houston,
458    #[serde(rename = "Buenos Aires")]
459    BuenosAires,
460    #[serde(rename = "Baltimore")]
461    Baltimore,
462    #[serde(rename = "San Salvador")]
463    SanSalvador,
464    #[serde(rename = "Istanbul")]
465    Istanbul,
466    #[serde(rename = "Huntington")]
467    Huntington,
468    #[serde(rename = "Nuuk")]
469    Nuuk,
470    #[serde(rename = "Quito")]
471    Quito,
472    #[serde(rename = "Vancouver")]
473    Vancouver,
474    #[serde(rename = "Dakar")]
475    Dakar,
476    #[serde(rename = "Montevideo")]
477    Montevideo,
478    #[serde(rename = "Sarajevo")]
479    Sarajevo,
480    #[serde(rename = "Algiers")]
481    Algiers,
482    #[serde(rename = "Mexico")]
483    Mexico,
484    #[serde(rename = "Doha")]
485    Doha,
486    #[serde(rename = "Los Angeles")]
487    LosAngeles,
488    #[serde(rename = "Riga")]
489    Riga,
490    #[serde(rename = "Kigali")]
491    Kigali,
492    #[serde(rename = "Oslo")]
493    Oslo,
494    #[serde(rename = "Taipei")]
495    Taipei,
496    #[serde(rename = "Port Louis")]
497    PortLouis,
498    #[serde(rename = "Auckland")]
499    Auckland,
500    #[serde(rename = "Port of Spain")]
501    PortOfSpain,
502    #[serde(rename = "Panama City")]
503    PanamaCity,
504    #[serde(rename = "La Paz")]
505    LaPaz,
506    #[serde(rename = "George Town")]
507    GeorgeTown,
508    #[serde(rename = "London")]
509    London,
510    #[serde(rename = "Tokyo")]
511    Tokyo,
512    #[serde(rename = "Phoenix")]
513    Phoenix,
514    #[serde(rename = "San Jose")]
515    SanJose,
516    #[serde(rename = "Zagreb")]
517    Zagreb,
518    #[serde(rename = "Buffalo")]
519    Buffalo,
520    #[serde(rename = "Marseille")]
521    Marseille,
522    #[serde(rename = "Santiago")]
523    Santiago,
524    #[serde(rename = "Yerevan")]
525    Yerevan,
526    #[serde(rename = "Kingston")]
527    Kingston,
528    #[serde(rename = "Ashburn")]
529    Ashburn,
530    #[serde(rename = "Lima")]
531    Lima,
532    #[serde(rename = "Milan")]
533    Milan,
534    #[serde(rename = "Tripoli")]
535    Tripoli,
536    #[serde(rename = "Dhaka")]
537    Dhaka,
538    #[serde(rename = "Stockholm")]
539    Stockholm,
540    #[serde(rename = "Addis Ababa")]
541    AddisAbaba,
542    #[serde(rename = "Omaha")]
543    Omaha,
544    #[serde(rename = "Toronto")]
545    Toronto,
546    #[serde(rename = "Berlin")]
547    Berlin,
548    #[serde(rename = "Burlington")]
549    Burlington,
550    #[serde(rename = "Charlotte")]
551    Charlotte,
552    #[serde(rename = "Hagatna")]
553    Hagatna,
554    #[serde(rename = "Belgrade")]
555    Belgrade,
556    #[serde(rename = "Paris")]
557    Paris,
558    #[serde(rename = "Athens")]
559    Athens,
560    #[serde(rename = "Luanda")]
561    Luanda,
562    #[serde(rename = "Providence")]
563    Providence,
564    #[serde(rename = "Lewiston")]
565    Lewiston,
566    #[serde(rename = "Tegucigalpa")]
567    Tegucigalpa,
568    #[serde(rename = "Denver")]
569    Denver,
570    #[serde(rename = "Sao Paulo")]
571    SaoPaulo,
572    #[serde(rename = "Osaka")]
573    Osaka,
574    #[serde(rename = "Maputo")]
575    Maputo,
576    #[serde(rename = "Kyiv")]
577    Kyiv,
578    #[serde(rename = "Ho Chi Minh City")]
579    HoChiMinhCity,
580    #[serde(rename = "Phnom Penh")]
581    PhnomPenh,
582    #[serde(rename = "Karachi")]
583    Karachi,
584    #[serde(rename = "Accra")]
585    Accra,
586    #[serde(rename = "Glasgow")]
587    Glasgow,
588    #[serde(rename = "Dubai")]
589    Dubai,
590    #[serde(rename = "Chisinau")]
591    Chisinau,
592    #[serde(rename = "Baku")]
593    Baku,
594    #[serde(rename = "Perth")]
595    Perth,
596    #[serde(rename = "Palermo")]
597    Palermo,
598    #[serde(rename = "McAllen")]
599    McAllen,
600    #[serde(rename = "Madrid")]
601    Madrid,
602    #[serde(rename = "Douglas")]
603    Douglas,
604    #[serde(rename = "Pittsburgh")]
605    Pittsburgh,
606    #[serde(rename = "Edinburgh")]
607    Edinburgh,
608    #[serde(rename = "Lagos")]
609    Lagos,
610    #[serde(rename = "Ljubljana")]
611    Ljubljana,
612    #[serde(rename = "Lisbon")]
613    Lisbon,
614    #[serde(rename = "Caracas")]
615    Caracas,
616    #[serde(rename = "Prague")]
617    Prague,
618    #[serde(rename = "Beirut")]
619    Beirut,
620    #[serde(rename = "Vientiane")]
621    Vientiane,
622    #[serde(rename = "Copenhagen")]
623    Copenhagen,
624    #[serde(rename = "Cairo")]
625    Cairo,
626    #[serde(rename = "Sydney")]
627    Sydney,
628    #[serde(rename = "Nouakchott")]
629    Nouakchott,
630    #[serde(rename = "Rome")]
631    Rome,
632    #[serde(rename = "Boston")]
633    Boston,
634    #[serde(rename = "Bangkok")]
635    Bangkok,
636    #[serde(rename = "New Haven")]
637    NewHaven,
638    #[serde(rename = "Astana")]
639    Astana,
640    #[serde(rename = "Valletta")]
641    Valletta,
642    #[serde(rename = "Mumbai")]
643    Mumbai,
644    #[serde(rename = "Bandar Seri Begawan")]
645    BandarSeriBegawan,
646    #[serde(rename = "Skopje")]
647    Skopje,
648    #[serde(rename = "Kathmandu")]
649    Kathmandu,
650    #[serde(rename = "Tbilisi")]
651    Tbilisi,
652    #[serde(rename = "Zurich")]
653    Zurich,
654    #[serde(rename = "Hong Kong")]
655    HongKong,
656    #[serde(rename = "Belmopan")]
657    Belmopan,
658    #[serde(rename = "Mogadishu")]
659    Mogadishu,
660    #[serde(rename = "Barcelona")]
661    Barcelona,
662    #[serde(rename = "Moroni")]
663    Moroni,
664    #[serde(rename = "New York")]
665    NewYork,
666    #[serde(rename = "Nashua")]
667    Nashua,
668    #[serde(rename = "Reykjavik")]
669    Reykjavik,
670    #[serde(rename = "San Juan")]
671    SanJuan,
672    #[serde(rename = "Johannesburg")]
673    Johannesburg,
674    #[serde(rename = "Amman")]
675    Amman,
676    #[serde(rename = "Nicosia")]
677    Nicosia,
678    #[serde(rename = "Nairobi")]
679    Nairobi,
680    #[serde(rename = "Colombo")]
681    Colombo,
682    #[serde(rename = "Tashkent")]
683    Tashkent,
684    #[serde(rename = "Miami")]
685    Miami,
686    #[serde(rename = "Rabat")]
687    Rabat,
688    #[serde(rename = "Hamilton")]
689    Hamilton,
690    #[serde(rename = "Saint Louis")]
691    SaintLouis,
692    #[serde(rename = "Atlanta")]
693    Atlanta,
694    #[serde(rename = "Montreal")]
695    Montreal,
696    #[serde(rename = "Tel Aviv")]
697    TelAviv,
698    #[serde(rename = "Ulaanbaatar")]
699    Ulaanbaatar,
700    #[serde(rename = "Port Moresby")]
701    PortMoresby,
702    #[serde(rename = "Seoul")]
703    Seoul,
704    #[serde(rename = "Nassau")]
705    Nassau,
706    #[serde(rename = "Salt Lake City")]
707    SaltLakeCity,
708    #[serde(rename = "Hamburg")]
709    Hamburg,
710    #[serde(rename = "San Francisco")]
711    SanFrancisco,
712    #[serde(rename = "Bucharest")]
713    Bucharest,
714    #[serde(rename = "Andorra la Vella")]
715    AndorraLaVella,
716    #[serde(rename = "Melbourne")]
717    Melbourne,
718    #[serde(rename = "Kuwait City")]
719    KuwaitCity,
720    #[serde(rename = "Helsinki")]
721    Helsinki,
722    #[serde(rename = "Nashville")]
723    Nashville,
724    #[serde(rename = "Saint Helier")]
725    SaintHelier,
726    #[serde(rename = "Brussels")]
727    Brussels,
728    #[serde(rename = "Dallas")]
729    Dallas,
730    #[serde(rename = "Budapest")]
731    Budapest,
732    #[serde(rename = "Monte Carlo")]
733    MonteCarlo,
734    #[serde(rename = "Bogota")]
735    Bogota,
736    #[serde(rename = "Vilnius")]
737    Vilnius,
738    #[serde(rename = "Tunis")]
739    Tunis,
740    #[serde(rename = "Amsterdam")]
741    Amsterdam,
742    #[serde(rename = "Tirana")]
743    Tirana,
744    #[serde(rename = "Podgorica")]
745    Podgorica,
746    #[serde(rename = "Fujairah")]
747    Fujairah,
748    #[serde(rename = "Vienna")]
749    Vienna,
750    #[serde(rename = "Bratislava")]
751    Bratislava,
752    #[serde(rename = "Seattle")]
753    Seattle,
754    #[serde(rename = "Baghdad")]
755    Baghdad,
756    #[serde(rename = "Frankfurt")]
757    Frankfurt,
758    #[serde(rename = "Manchester")]
759    Manchester,
760    #[serde(rename = "Trenton")]
761    Trenton,
762    #[serde(rename = "Asuncion")]
763    Asuncion,
764    #[serde(rename = "Singapore")]
765    Singapore,
766    #[serde(rename = "Vaduz")]
767    Vaduz,
768    #[serde(rename = "Adelaide")]
769    Adelaide,
770    #[serde(rename = "Hanoi")]
771    Hanoi,
772    #[serde(rename = "Tallinn")]
773    Tallinn,
774    #[serde(rename = "Santo Domingo")]
775    SantoDomingo,
776    #[serde(rename = "Manama")]
777    Manama,
778    #[serde(rename = "Kansas City")]
779    KansasCity,
780    #[serde(rename = "Kabul")]
781    Kabul,
782    #[serde(rename = "Naypyidaw")]
783    Naypyidaw,
784    #[serde(rename = "Manila")]
785    Manila,
786    #[serde(rename = "Strasbourg")]
787    Strasbourg,
788    Paramaribo,
789}