--- a/src/connection.h
+++ b/src/connection.h
@@ -42,7 +42,8 @@
 	unsigned int decryptin:1;			/* 1 if we have to decrypt incoming traffic */
 	unsigned int mst:1;				/* 1 if this connection is part of a minimum spanning tree */
 	unsigned int proxy_passed:1;			/* 1 if we are connecting via a proxy and we have finished talking with it */
-	unsigned int unused:22;
+	unsigned int tarpit:1;                          /* 1 if the connection should be added to the tarpit */
+	unsigned int unused:21;
 } connection_status_t;
 
 #include "edge.h"
--- a/src/net.c
+++ b/src/net.c
@@ -158,6 +158,22 @@
 	return max;
 }
 
+/* Put a misbehaving connection in the tarpit */
+void tarpit(int fd) {
+	static int pits[10] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
+	static int next_pit = 0;
+
+	if(pits[next_pit] != -1) {
+		closesocket(pits[next_pit]);
+	}
+
+	pits[next_pit++] = fd;
+
+	if(next_pit >= sizeof pits / sizeof pits[0]) {
+		next_pit = 0;
+	}
+}
+
 /*
   Terminate a connection:
   - Close the socket
@@ -178,8 +194,13 @@
 	if(c->node)
 		c->node->connection = NULL;
 
-	if(c->socket)
-		closesocket(c->socket);
+	if(c->socket) {
+		if(c->status.tarpit) {
+			tarpit(c->socket);
+		} else {
+			closesocket(c->socket);
+		}
+	}
 
 	if(c->edge) {
 		if(!c->node) {
@@ -266,6 +287,7 @@
 					closesocket(c->socket);
 					do_outgoing_connection(c);
 				} else {
+					c->status.tarpit = true;
 					terminate_connection(c, false);
 				}
 			}
@@ -345,6 +367,7 @@
 
 		if(FD_ISSET(c->socket, readset)) {
 			if(!receive_meta(c)) {
+				c->status.tarpit = true;
 				terminate_connection(c, c->status.active);
 				continue;
 			}
--- a/src/net.h
+++ b/src/net.h
@@ -150,6 +150,7 @@
 extern bool read_rsa_public_key(struct connection_t *);
 extern void send_mtu_probe(struct node_t *);
 extern void load_all_subnets(void);
+extern void tarpit(int fd);
 
 #ifndef HAVE_MINGW
 #define closesocket(s) close(s)
--- a/src/net_socket.c
+++ b/src/net_socket.c
@@ -552,6 +552,9 @@
   new connection
 */
 bool handle_new_meta_connection(int sock) {
+	static const int max_accept_burst = 10;
+	static int last_accept_burst;
+	static int last_accept_time;
 	connection_t *c;
 	sockaddr_t sa;
 	int fd;
@@ -564,6 +567,22 @@
 		return false;
 	}
 
+	if(last_accept_time == now) {
+		last_accept_burst++;
+
+		if(last_accept_burst >= max_accept_burst) {
+			if(last_accept_burst == max_accept_burst) {
+				ifdebug(CONNECTIONS) logger(LOG_WARNING, "Throttling incoming connections");
+			}
+
+			tarpit(fd);
+			return false;
+		}
+	} else {
+		last_accept_burst = 0;
+		last_accept_time = now;
+	}
+
 	sockaddrunmap(&sa);
 
 	c = new_connection();
@@ -585,7 +604,6 @@
 	connection_add(c);
 
 	c->allow_request = ID;
-	send_id(c);
 
 	return true;
 }
--- a/src/protocol_auth.c
+++ b/src/protocol_auth.c
@@ -59,7 +59,7 @@
 
 	/* Check if identity is a valid name */
 
-	if(!check_id(name)) {
+	if(!check_id(name) || !strcmp(name, myself->name)) {
 		logger(LOG_ERR, "Got bad %s from %s (%s): %s", "ID", c->name,
 			   c->hostname, "invalid name");
 		return false;
@@ -91,6 +91,11 @@
 		if(!c->config_tree)
 			init_configuration(&c->config_tree);
 		c->allow_request = ACK;
+
+		if(!c->outgoing) {
+			send_id(c);
+		}
+
 		return send_ack(c);
 	}
 
@@ -110,6 +115,10 @@
 
 	c->allow_request = METAKEY;
 
+	if(!c->outgoing) {
+		send_id(c);
+	}
+
 	return send_metakey(c);
 }
 
@@ -292,7 +301,8 @@
 		c->inbudget = byte_budget(c->incipher);
 		c->status.decryptin = true;
 	} else {
-		c->incipher = NULL;
+		logger(LOG_ERR, "%s (%s) uses null cipher!", c->name, c->hostname);
+		return false;
 	}
 
 	c->inmaclength = maclength;
@@ -310,7 +320,8 @@
 			return false;
 		}
 	} else {
-		c->indigest = NULL;
+		logger(LOG_ERR, "%s (%s) uses null digest!", c->name, c->hostname);
+		return false;
 	}
 
 	c->incompression = compression;
@@ -384,7 +395,11 @@
 
 	/* Rest is done by send_chal_reply() */
 
-	return send_chal_reply(c);
+	if(c->outgoing) {
+		return send_chal_reply(c);
+	} else {
+		return true;
+	}
 }
 
 bool send_chal_reply(connection_t *c) {
@@ -482,6 +497,10 @@
 
 	c->allow_request = ACK;
 
+	if(!c->outgoing) {
+		send_chal_reply(c);
+	}
+
 	return send_ack(c);
 }
 
--- a/src/protocol_edge.c
+++ b/src/protocol_edge.c
@@ -70,7 +70,7 @@
 
 	/* Check if names are valid */
 
-	if(!check_id(from_name) || !check_id(to_name)) {
+	if(!check_id(from_name) || !check_id(to_name) || !strcmp(from_name, to_name)) {
 		logger(LOG_ERR, "Got bad %s from %s (%s): %s", "ADD_EDGE", c->name,
 			   c->hostname, "invalid name");
 		return false;
@@ -192,7 +192,7 @@
 
 	/* Check if names are valid */
 
-	if(!check_id(from_name) || !check_id(to_name)) {
+	if(!check_id(from_name) || !check_id(to_name) || !strcmp(from_name, to_name)) {
 		logger(LOG_ERR, "Got bad %s from %s (%s): %s", "DEL_EDGE", c->name,
 			   c->hostname, "invalid name");
 		return false;
--- a/src/protocol_key.c
+++ b/src/protocol_key.c
@@ -274,6 +274,11 @@
 			return true;
 		}
 	} else {
+		if(from->outkeylength != 1) {
+			logger(LOG_ERR, "Node %s (%s) uses wrong keylength!", from->name, from->hostname);
+			return true;
+		}
+
 		from->outcipher = NULL;
 	}
 
