… | |
… | |
62 | |
62 | |
63 | static const rsachallenge & |
63 | static const rsachallenge & |
64 | challenge_bytes () |
64 | challenge_bytes () |
65 | { |
65 | { |
66 | static rsachallenge challenge; |
66 | static rsachallenge challenge; |
67 | static double challenge_ttl; // time this challenge needs to be recreated |
67 | static tstamp challenge_ttl; // time this challenge needs to be recreated |
68 | |
68 | |
69 | if (NOW > challenge_ttl) |
69 | if (NOW > challenge_ttl) |
70 | { |
70 | { |
71 | RAND_bytes ((unsigned char *)&challenge, sizeof (challenge)); |
71 | RAND_bytes ((unsigned char *)&challenge, sizeof (challenge)); |
72 | challenge_ttl = NOW + CHALLENGE_TTL; |
72 | challenge_ttl = NOW + CHALLENGE_TTL; |
… | |
… | |
264 | { |
264 | { |
265 | for (i = QUEUEDEPTH; --i > 0; ) |
265 | for (i = QUEUEDEPTH; --i > 0; ) |
266 | delete queue[i]; |
266 | delete queue[i]; |
267 | } |
267 | } |
268 | |
268 | |
|
|
269 | struct net_rateinfo { |
|
|
270 | u32 host; |
|
|
271 | double pcnt, diff; |
|
|
272 | tstamp last; |
|
|
273 | }; |
|
|
274 | |
269 | // only do action once every x seconds per host. |
275 | // only do action once every x seconds per host whole allowing bursts. |
270 | // currently this is quite a slow implementation, |
276 | // this implementation ("splay list" ;) is inefficient, |
271 | // but suffices for normal operation. |
277 | // but low on resources. |
272 | struct u32_rate_limiter : private map<u32, tstamp> |
278 | struct net_rate_limiter : private list<net_rateinfo> |
273 | { |
279 | { |
274 | tstamp every; |
280 | static const double ALPHA = 1. - 1. / 90.; // allow bursts |
|
|
281 | static const double CUTOFF = 20.; // one event every CUTOFF seconds |
|
|
282 | static const double EXPIRE = CUTOFF * 30.; // expire entries after this time |
275 | |
283 | |
276 | bool can (u32 host); |
284 | bool can (u32 host); |
277 | |
|
|
278 | u32_rate_limiter (tstamp every = 1) |
|
|
279 | { |
|
|
280 | this->every = every; |
|
|
281 | } |
|
|
282 | }; |
|
|
283 | |
|
|
284 | struct net_rate_limiter : u32_rate_limiter |
|
|
285 | { |
|
|
286 | bool can (SOCKADDR *sa) { return u32_rate_limiter::can((u32)sa->sin_addr.s_addr); } |
285 | bool can (SOCKADDR *sa) { return can((u32)sa->sin_addr.s_addr); } |
287 | bool can (sockinfo &si) { return u32_rate_limiter::can((u32)si.host); } |
286 | bool can (sockinfo &si) { return can((u32)si.host); } |
|
|
287 | }; |
288 | |
288 | |
289 | net_rate_limiter (tstamp every) : u32_rate_limiter (every) {} |
289 | net_rate_limiter auth_rate_limiter, reset_rate_limiter; |
290 | }; |
|
|
291 | |
290 | |
292 | bool u32_rate_limiter::can (u32 host) |
291 | bool net_rate_limiter::can (u32 host) |
293 | { |
292 | { |
294 | iterator i; |
293 | iterator i; |
295 | |
294 | |
296 | for (i = begin (); i != end (); ) |
295 | for (i = begin (); i != end (); ) |
297 | if (i->second <= NOW) |
296 | if (i->host == host) |
298 | { |
297 | break; |
|
|
298 | else if (i->last < NOW - EXPIRE) |
299 | erase (i); |
299 | i = erase (i); |
300 | i = begin (); |
|
|
301 | } |
|
|
302 | else |
300 | else |
303 | ++i; |
301 | i++; |
304 | |
302 | |
305 | i = find (host); |
|
|
306 | |
|
|
307 | if (i != end ()) |
303 | if (i == end ()) |
308 | return false; |
304 | { |
|
|
305 | net_rateinfo ri; |
309 | |
306 | |
310 | insert (value_type (host, NOW + every)); |
307 | ri.host = host; |
|
|
308 | ri.pcnt = 1.; |
|
|
309 | ri.diff = CUTOFF * (1. / (1. - ALPHA)); |
|
|
310 | ri.last = NOW; |
311 | |
311 | |
|
|
312 | push_front (ri); |
|
|
313 | |
312 | return true; |
314 | return true; |
|
|
315 | } |
|
|
316 | else |
|
|
317 | { |
|
|
318 | net_rateinfo ri (*i); |
|
|
319 | erase (i); |
|
|
320 | |
|
|
321 | ri.pcnt = ri.pcnt * ALPHA; |
|
|
322 | ri.diff = ri.diff * ALPHA + (NOW - ri.last); |
|
|
323 | |
|
|
324 | ri.last = NOW; |
|
|
325 | |
|
|
326 | bool send = ri.diff / ri.pcnt > CUTOFF; |
|
|
327 | |
|
|
328 | if (send) |
|
|
329 | ri.pcnt++; |
|
|
330 | |
|
|
331 | //printf ("RATE %d %f,%f = %f > %f\n", !!send, ri.pcnt, ri.diff, ri.diff / ri.pcnt, CUTOFF); |
|
|
332 | |
|
|
333 | push_front (ri); |
|
|
334 | |
|
|
335 | return send; |
|
|
336 | } |
313 | } |
337 | } |
314 | |
338 | |
315 | ///////////////////////////////////////////////////////////////////////////// |
339 | ///////////////////////////////////////////////////////////////////////////// |
316 | |
340 | |
317 | static void next_wakeup (time_t next) |
341 | static void next_wakeup (time_t next) |
… | |
… | |
665 | } |
689 | } |
666 | |
690 | |
667 | void |
691 | void |
668 | connection::send_reset (SOCKADDR *dsa) |
692 | connection::send_reset (SOCKADDR *dsa) |
669 | { |
693 | { |
670 | static net_rate_limiter limiter(1); |
|
|
671 | |
|
|
672 | if (limiter.can (dsa) && connectmode != conf_node::C_DISABLED) |
694 | if (reset_rate_limiter.can (dsa) && connectmode != conf_node::C_DISABLED) |
673 | { |
695 | { |
674 | config_packet *pkt = new config_packet; |
696 | config_packet *pkt = new config_packet; |
675 | |
697 | |
676 | pkt->setup (vpn_packet::PT_RESET, conf->id); |
698 | pkt->setup (vpn_packet::PT_RESET, conf->id); |
677 | vpn->send_vpn_packet (pkt, dsa, IPTOS_MINCOST); |
699 | vpn->send_vpn_packet (pkt, dsa, IPTOS_MINCOST); |
… | |
… | |
693 | } |
715 | } |
694 | |
716 | |
695 | void |
717 | void |
696 | connection::send_auth (auth_subtype subtype, SOCKADDR *sa, const rsachallenge *k) |
718 | connection::send_auth (auth_subtype subtype, SOCKADDR *sa, const rsachallenge *k) |
697 | { |
719 | { |
698 | static net_rate_limiter limiter(0.2); |
|
|
699 | |
|
|
700 | if (subtype != AUTH_INIT || limiter.can (sa)) |
720 | if (subtype == AUTH_REPLY || auth_rate_limiter.can (sa)) |
701 | { |
721 | { |
702 | if (!k) |
722 | if (!k) |
703 | k = gen_challenge (seqrand, sa); |
723 | k = gen_challenge (seqrand, sa); |
704 | |
724 | |
705 | auth_packet *pkt = new auth_packet (conf->id, subtype); |
725 | auth_packet *pkt = new auth_packet (conf->id, subtype); |
… | |
… | |
732 | { |
752 | { |
733 | reset_dstaddr (); |
753 | reset_dstaddr (); |
734 | if (sa.sin_addr.s_addr) |
754 | if (sa.sin_addr.s_addr) |
735 | if (retry_cnt < 4) |
755 | if (retry_cnt < 4) |
736 | send_auth (AUTH_INIT, &sa); |
756 | send_auth (AUTH_INIT, &sa); |
737 | else |
757 | else if (auth_rate_limiter.can (&sa)) |
738 | send_ping (&sa, 0); |
758 | send_ping (&sa, 0); |
739 | } |
759 | } |
740 | else |
760 | else |
741 | vpn->connect_request (conf->id); |
761 | vpn->connect_request (conf->id); |
742 | } |
762 | } |
… | |
… | |
829 | conf->id, pkt->typ (), pkt->src (), pkt->dst ()); |
849 | conf->id, pkt->typ (), pkt->src (), pkt->dst ()); |
830 | |
850 | |
831 | switch (pkt->typ ()) |
851 | switch (pkt->typ ()) |
832 | { |
852 | { |
833 | case vpn_packet::PT_PING: |
853 | case vpn_packet::PT_PING: |
834 | send_ping (ssa, 1); // pong |
|
|
835 | break; |
|
|
836 | |
|
|
837 | case vpn_packet::PT_PONG: |
|
|
838 | // we send pings instead of auth packets after some retries, |
854 | // we send pings instead of auth packets after some retries, |
839 | // so reset the retry counter and establish a conenction |
855 | // so reset the retry counter and establish a conenction |
840 | // when we receive a pong. |
856 | // when we receive a pong. |
841 | if (!ictx && !octx) |
857 | if (!ictx && !octx) |
842 | { |
858 | { |
843 | retry_cnt = 0; |
859 | retry_cnt = 0; |
844 | establish_connection.at = 0; |
860 | establish_connection.at = 0; |
845 | establish_connection (); |
861 | establish_connection (); |
846 | } |
862 | } |
|
|
863 | else |
|
|
864 | send_ping (ssa, 1); // pong |
847 | |
865 | |
|
|
866 | break; |
|
|
867 | |
|
|
868 | case vpn_packet::PT_PONG: |
848 | break; |
869 | break; |
849 | |
870 | |
850 | case vpn_packet::PT_RESET: |
871 | case vpn_packet::PT_RESET: |
851 | { |
872 | { |
852 | reset_connection (); |
873 | reset_connection (); |
… | |
… | |
882 | |
903 | |
883 | if (!k) |
904 | if (!k) |
884 | { |
905 | { |
885 | slog (L_ERR, _("challenge from %s (%s) illegal or corrupted"), |
906 | slog (L_ERR, _("challenge from %s (%s) illegal or corrupted"), |
886 | conf->nodename, (const char *)sockinfo (ssa)); |
907 | conf->nodename, (const char *)sockinfo (ssa)); |
|
|
908 | send_reset (ssa); |
887 | break; |
909 | break; |
888 | } |
910 | } |
889 | |
911 | |
890 | retry_cnt = 0; |
912 | retry_cnt = 0; |
891 | establish_connection.set (NOW + 8); //? ;) |
913 | establish_connection.set (NOW + 8); //? ;) |
… | |
… | |
1444 | } |
1466 | } |
1445 | |
1467 | |
1446 | ts = TSTAMP_CANCEL; |
1468 | ts = TSTAMP_CANCEL; |
1447 | } |
1469 | } |
1448 | |
1470 | |
|
|
1471 | #include <sys/time.h>//D |
1449 | vpn::vpn (void) |
1472 | vpn::vpn (void) |
1450 | : udp_ev_watcher (this, &vpn::udp_ev) |
1473 | : udp_ev_watcher (this, &vpn::udp_ev) |
1451 | , vpn_ev_watcher (this, &vpn::vpn_ev) |
1474 | , vpn_ev_watcher (this, &vpn::vpn_ev) |
1452 | , event (this, &vpn::event_cb) |
1475 | , event (this, &vpn::event_cb) |
1453 | { |
1476 | { |