.Va Mode
is set to
.Qq switch .
+.It Va MaxConnectionBurst Li = Ar count Pq 100
+This option controls how many connections tinc accepts in quick succession.
+If there are more connections than the given number in a short time interval,
+tinc will reduce the number of accepted connections to only one per second,
+until the burst has passed.
.It Va MaxTimeout Li = Ar seconds Pq 900
This is the maximum delay before trying to reconnect to other tinc daemons.
.It Va Mode Li = router | switch | hub Pq router
This option controls the amount of time MAC addresses are kept before they are removed.
This only has effect when Mode is set to "switch".
+@cindex MaxConnectionBurst
+@item MaxConnectionBurst = <@var{count}> (100)
+This option controls how many connections tinc accepts in quick succession.
+If there are more connections than the given number in a short time interval,
+tinc will reduce the number of accepted connections to only one per second,
+until the burst has passed.
+
@cindex Name
@item Name = <@var{name}> [required]
This is a symbolic name for this connection.
pass all traffic, but leaves tinc vulnerable to replay-based attacks on your
traffic.
-
@cindex StrictSubnets
@item StrictSubnets <yes|no> (no) [experimental]
When this option is enabled tinc will only use Subnet statements which are
extern int keylifetime;
extern int udp_rcvbuf;
extern int udp_sndbuf;
+extern int max_connection_burst;
extern bool do_prune;
extern char *myport;
extern int autoconnect;
get_config_bool(lookup_config(config_tree, "TunnelServer"), &tunnelserver);
strictsubnets |= tunnelserver;
-
+ if(get_config_int(lookup_config(config_tree, "MaxConnectionBurst"), &max_connection_burst)) {
+ if(max_connection_burst <= 0) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "MaxConnectionBurst cannot be negative!");
+ return false;
+ }
+ }
if(get_config_int(lookup_config(config_tree, "UDPRcvBuf"), &udp_rcvbuf)) {
if(udp_rcvbuf <= 0) {
int seconds_till_retry = 5;
int udp_rcvbuf = 0;
int udp_sndbuf = 0;
+int max_connection_burst = 100;
listen_socket_t listen_socket[MAXSOCKETS];
int listen_sockets;
sockaddrunmap(&sa);
+ // Check if we get many connections from the same host
+
+ static sockaddr_t prev_sa;
+ static time_t prev_time;
+ static int tarpit = -1;
+
+ if(tarpit >= 0) {
+ closesocket(tarpit);
+ tarpit = -1;
+ }
+
+ if(prev_time == now.tv_sec && !sockaddrcmp_noport(&sa, &prev_sa)) {
+ // if so, keep the connection open but ignore it completely.
+ tarpit = fd;
+ return;
+ }
+
+ memcpy(&prev_sa, &sa, sizeof sa);
+ prev_time = now.tv_sec;
+
+ // Check if we get many connections from different hosts
+
+ static int connection_burst;
+ static int connection_burst_time;
+
+ if(now.tv_sec - connection_burst_time > connection_burst)
+ connection_burst = 0;
+ else
+ connection_burst -= now.tv_sec - connection_burst_time;
+
+ connection_burst_time = now.tv_sec;
+ connection_burst++;
+
+ if(connection_burst >= max_connection_burst) {
+ connection_burst = max_connection_burst;
+ tarpit = fd;
+ return;
+ }
+
+ // Accept the new connection
+
c = new_connection();
c->name = xstrdup("<unknown>");
c->outcipher = myself->connection->outcipher;
{"KeyExpire", VAR_SERVER},
{"LocalDiscovery", VAR_SERVER},
{"MACExpire", VAR_SERVER},
+ {"MaxConnectionBurst", VAR_SERVER},
{"MaxOutputBufferSize", VAR_SERVER},
{"MaxTimeout", VAR_SERVER},
{"Mode", VAR_SERVER | VAR_SAFE},