… | |
… | |
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); |
… | |
… | |
723 | { |
743 | { |
724 | double retry_int = double (retry_cnt & 3 ? (retry_cnt & 3) : 1 << (retry_cnt >> 2)) * 0.25; |
744 | double retry_int = double (retry_cnt & 3 ? (retry_cnt & 3) : 1 << (retry_cnt >> 2)) * 0.25; |
725 | |
745 | |
726 | if (retry_int < 3600 * 8) |
746 | if (retry_int < 3600 * 8) |
727 | retry_cnt++; |
747 | retry_cnt++; |
728 | |
|
|
729 | if (connectmode == conf_node::C_ONDEMAND |
|
|
730 | && retry_int > ::conf.keepalive) |
|
|
731 | retry_int = ::conf.keepalive; |
|
|
732 | |
748 | |
733 | ts = NOW + retry_int; |
749 | ts = NOW + retry_int; |
734 | |
750 | |
735 | if (conf->hostname) |
751 | if (conf->hostname) |
736 | { |
752 | { |
737 | reset_dstaddr (); |
753 | reset_dstaddr (); |
738 | if (sa.sin_addr.s_addr) |
754 | if (sa.sin_addr.s_addr) |
739 | if (retry_cnt < 4) |
755 | if (retry_cnt < 4) |
740 | send_auth (AUTH_INIT, &sa); |
756 | send_auth (AUTH_INIT, &sa); |
741 | else |
757 | else if (auth_rate_limiter.can (&sa)) |
742 | send_ping (&sa, 0); |
758 | send_ping (&sa, 0); |
743 | } |
759 | } |
744 | else |
760 | else |
745 | vpn->connect_request (conf->id); |
761 | vpn->connect_request (conf->id); |
746 | } |
762 | } |
… | |
… | |
833 | conf->id, pkt->typ (), pkt->src (), pkt->dst ()); |
849 | conf->id, pkt->typ (), pkt->src (), pkt->dst ()); |
834 | |
850 | |
835 | switch (pkt->typ ()) |
851 | switch (pkt->typ ()) |
836 | { |
852 | { |
837 | case vpn_packet::PT_PING: |
853 | case vpn_packet::PT_PING: |
838 | send_ping (ssa, 1); // pong |
|
|
839 | break; |
|
|
840 | |
|
|
841 | case vpn_packet::PT_PONG: |
|
|
842 | // we send pings instead of auth packets after some retries, |
854 | // we send pings instead of auth packets after some retries, |
843 | // so reset the retry counter and establish a conenction |
855 | // so reset the retry counter and establish a conenction |
844 | // when we receive a pong. |
856 | // when we receive a pong. |
845 | if (!ictx && !octx) |
857 | if (!ictx && !octx) |
846 | { |
858 | { |
847 | retry_cnt = 0; |
859 | retry_cnt = 0; |
848 | establish_connection.at = 0; |
860 | establish_connection.at = 0; |
849 | establish_connection (); |
861 | establish_connection (); |
850 | } |
862 | } |
|
|
863 | else |
|
|
864 | send_ping (ssa, 1); // pong |
851 | |
865 | |
|
|
866 | break; |
|
|
867 | |
|
|
868 | case vpn_packet::PT_PONG: |
852 | break; |
869 | break; |
853 | |
870 | |
854 | case vpn_packet::PT_RESET: |
871 | case vpn_packet::PT_RESET: |
855 | { |
872 | { |
856 | reset_connection (); |
873 | reset_connection (); |
… | |
… | |
886 | |
903 | |
887 | if (!k) |
904 | if (!k) |
888 | { |
905 | { |
889 | slog (L_ERR, _("challenge from %s (%s) illegal or corrupted"), |
906 | slog (L_ERR, _("challenge from %s (%s) illegal or corrupted"), |
890 | conf->nodename, (const char *)sockinfo (ssa)); |
907 | conf->nodename, (const char *)sockinfo (ssa)); |
|
|
908 | send_reset (ssa); |
891 | break; |
909 | break; |
892 | } |
910 | } |
893 | |
911 | |
894 | retry_cnt = 0; |
912 | retry_cnt = 0; |
895 | establish_connection.set (NOW + 8); //? ;) |
913 | establish_connection.set (NOW + 8); //? ;) |
… | |
… | |
1448 | } |
1466 | } |
1449 | |
1467 | |
1450 | ts = TSTAMP_CANCEL; |
1468 | ts = TSTAMP_CANCEL; |
1451 | } |
1469 | } |
1452 | |
1470 | |
|
|
1471 | #include <sys/time.h>//D |
1453 | vpn::vpn (void) |
1472 | vpn::vpn (void) |
1454 | : udp_ev_watcher (this, &vpn::udp_ev) |
1473 | : udp_ev_watcher (this, &vpn::udp_ev) |
1455 | , vpn_ev_watcher (this, &vpn::vpn_ev) |
1474 | , vpn_ev_watcher (this, &vpn::vpn_ev) |
1456 | , event (this, &vpn::event_cb) |
1475 | , event (this, &vpn::event_cb) |
1457 | { |
1476 | { |