diff --git a/crypt.cpp b/crypt.cpp
index 4aa98fa..461377f 100644
--- a/crypt.cpp
+++ b/crypt.cpp
@@ -26,6 +26,12 @@ public:
 	inline Private(Crypt &crypt):
 		crypt(crypt), key(), iv(), tq() { }
 	
+	inline ~Private() {
+		memset(key, 0, sizeof(key));
+		memset(iv, 0, sizeof(iv));
+		memset(tq, 0, sizeof(tq));
+	}
+	
 	inline void setTimeQwant(Time timeQwant, int index) {
 		if (tq[index] == timeQwant) return;
 		tq[index] = timeQwant;
diff --git a/main.cpp b/main.cpp
new file mode 100644
index 0000000..226d583
--- /dev/null
+++ b/main.cpp
@@ -0,0 +1,83 @@
+
+#include <cstdio>
+#include <cerrno>
+#include <cstring>
+
+#include "tunnel.h"
+
+
+bool parseAddress(const char *str, Address &address) {
+	address = Address();
+	sscanf( str, "%hhu.%hhu.%hhu.%hhu:%hu",
+			&address.ip[0], &address.ip[1], &address.ip[2], &address.ip[3],
+			&address.port );
+	if (!address.port) {
+		printf("Wrong ip-address: [%s]\n", str);
+		return false;
+	}
+	return true;
+}
+
+
+int main(int argc, char **argv) {
+	
+	// parse args
+	
+	Address localUdp, remoteUdp, localTcp, remoteTcp;
+	if (argc == 5) {
+		parseAddress(argv[2], localUdp);
+		parseAddress(argv[3], remoteUdp);
+		parseAddress(argv[4], localTcp);
+		if (!localUdp.port || !remoteUdp.port || !localTcp.port) return 1;
+	} else
+	if (argc == 4) {
+		parseAddress(argv[2], localUdp);
+		parseAddress(argv[3], remoteTcp);
+		if (!localUdp.port || !remoteTcp.port) return 1;
+	} else {
+		printf("Usage: %s keyfile localUdp:port remoteUdp:port localTcp:port\n", argv[0]);
+		printf("   or: %s keyfile localUdp:port remoteTcp:port\n", argv[0]);
+		return 1;
+	}
+	
+	// load key
+	
+	FILE *f = fopen(argv[1], "r");
+	if (!f) {
+		printf("Cannot open keyfile: [%s]\n", argv[1]);
+		return 1;
+	}
+	int maxSize = 1024*1024;
+	char *key = (char*)calloc(1, maxSize);
+	char *c = key, *e = c + maxSize - 1;
+	int i = 0;
+	while((i = fgetc(f)) > 0 && c < e) *c++ = i;
+	if (i != EOF || errno) {
+		printf("Cannot read keyfile: [%s]\n", argv[1]);
+		memset(key, 0, maxSize);
+		free(key);
+		fclose(f);
+	}
+	fclose(f);
+	
+	// init tunnel
+	
+	Tunnel tunnel;
+	
+	if ( !tunnel.initUdpServer(localUdp, remoteTcp, key) ) {
+		memset(key, 0, maxSize);
+		free(key);
+		return 1;
+	}
+	memset(key, 0, maxSize);
+	free(key);
+
+	if ( localTcp.port && remoteUdp.port
+	  && !tunnel.initTcpServer(localTcp, remoteUdp) )
+		return 1;
+	
+	tunnel.run();
+	
+	return 0;
+}
+