allways write exceptions to log
[anytun.git] / src / anytun.cpp
blobe995fa8e3c358fe94bbd4b0fce9efa946ceaabad
1 /*
2 * anytun
4 * The secure anycast tunneling protocol (satp) defines a protocol used
5 * for communication between any combination of unicast and anycast
6 * tunnel endpoints. It has less protocol overhead than IPSec in Tunnel
7 * mode and allows tunneling of every ETHER TYPE protocol (e.g.
8 * ethernet, ip, arp ...). satp directly includes cryptography and
9 * message authentication based on the methodes used by SRTP. It is
10 * intended to deliver a generic, scaleable and secure solution for
11 * tunneling and relaying of packets of any protocol.
14 * Copyright (C) 2007-2008 Othmar Gsenger, Erwin Nindl,
15 * Christian Pointner <satp@wirdorange.org>
17 * This file is part of Anytun.
19 * Anytun is free software: you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License version 3 as
21 * published by the Free Software Foundation.
23 * Anytun is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
28 * You should have received a copy of the GNU General Public License
29 * along with anytun. If not, see <http://www.gnu.org/licenses/>.
32 #include <iostream>
33 #include <fstream>
36 #include <boost/bind.hpp>
37 #ifndef NOCRYPT
38 #include <gcrypt.h>
39 #endif
40 #include <cerrno> // for ENOMEM
42 #include "datatypes.h"
44 #include "log.h"
45 #include "buffer.h"
46 #include "plainPacket.h"
47 #include "encryptedPacket.h"
48 #include "cipher.h"
49 #include "keyDerivation.h"
50 #include "authAlgo.h"
51 #include "cipherFactory.h"
52 #include "authAlgoFactory.h"
53 #include "keyDerivationFactory.h"
54 #ifndef NOSIGNALCONTROLLER
55 #include "signalController.h"
56 #endif
57 #include "packetSource.h"
58 #include "tunDevice.h"
59 #include "options.h"
60 #include "seqWindow.h"
61 #include "connectionList.h"
62 #ifndef NOROUTING
63 #include "routingTable.h"
64 #include "networkAddress.h"
65 #endif
67 #include "syncQueue.h"
68 #include "syncCommand.h"
70 #ifndef ANYTUN_NOSYNC
71 #include "syncServer.h"
72 #include "syncClient.h"
73 #include "syncOnConnect.hpp"
74 #endif
76 #include "threadParam.h"
77 #define MAX_PACKET_LENGTH 1600
79 #include "cryptinit.hpp"
80 #include "daemon.hpp"
81 #include "sysexec.hpp"
83 #define SESSION_KEYLEN_AUTH 20 // TODO: hardcoded size
84 #define SESSION_KEYLEN_ENCR 16 // TODO: hardcoded size
85 #define SESSION_KEYLEN_SALT 14 // TODO: hardcoded size
87 void createConnection(const PacketSourceEndpoint & remote_end, ConnectionList & cl, window_size_t seqSize, SyncQueue & queue, mux_t mux)
89 SeqWindow * seq= new SeqWindow(seqSize);
90 seq_nr_t seq_nr_=0;
91 KeyDerivation * kd = KeyDerivationFactory::create(gOpt.getKdPrf());
92 kd->init(gOpt.getKey(), gOpt.getSalt());
93 cLog.msg(Log::PRIO_NOTICE) << "added connection remote host " << remote_end;
95 ConnectionParam connparam ( (*kd), (*seq), seq_nr_, remote_end);
96 cl.addConnection(connparam,mux);
97 SyncCommand sc (cl,mux);
98 queue.push(sc);
99 #ifndef NOROUTING
100 if (gOpt.getIfconfigParamRemoteNetmask() != "")
102 NetworkAddress addr(gOpt.getIfconfigParamRemoteNetmask());
103 NetworkPrefix prefix(addr,128);
104 gRoutingTable.addRoute(prefix,mux);
105 SyncCommand sc2 (prefix);
106 queue.push(sc2);
108 #endif
111 bool checkPacketSeqNr(EncryptedPacket& pack,ConnectionParam& conn)
113 // compare sender_id and seq with window
114 if(conn.seq_window_.hasSeqNr(pack.getSenderId(), pack.getSeqNr()))
116 cLog.msg(Log::PRIO_NOTICE) << "Replay attack from " << conn.remote_end_
117 << " seq:"<<pack.getSeqNr() << " sid: "<<pack.getSenderId();
118 return false;
121 conn.seq_window_.addSeqNr(pack.getSenderId(), pack.getSeqNr());
122 return true;
125 void sender(void* p)
127 try
129 ThreadParam* param = reinterpret_cast<ThreadParam*>(p);
131 std::auto_ptr<Cipher> c(CipherFactory::create(gOpt.getCipher()));
132 std::auto_ptr<AuthAlgo> a(AuthAlgoFactory::create(gOpt.getAuthAlgo()) );
134 PlainPacket plain_packet(MAX_PACKET_LENGTH);
135 EncryptedPacket encrypted_packet(MAX_PACKET_LENGTH);
137 Buffer session_key(u_int32_t(SESSION_KEYLEN_ENCR)); // TODO: hardcoded size
138 Buffer session_salt(u_int32_t(SESSION_KEYLEN_SALT)); // TODO: hardcoded size
139 Buffer session_auth_key(u_int32_t(SESSION_KEYLEN_AUTH)); // TODO: hardcoded size
141 //TODO replace mux
142 u_int16_t mux = gOpt.getMux();
143 PacketSourceEndpoint emptyEndpoint;
144 while(1)
146 plain_packet.setLength(MAX_PACKET_LENGTH);
147 encrypted_packet.withAuthTag(false);
148 encrypted_packet.setLength(MAX_PACKET_LENGTH);
150 // read packet from device
151 u_int32_t len = param->dev.read(plain_packet.getPayload(), plain_packet.getPayloadLength());
152 plain_packet.setPayloadLength(len);
153 // set payload type
154 if(param->dev.getType() == TYPE_TUN)
155 plain_packet.setPayloadType(PAYLOAD_TYPE_TUN);
156 else if(param->dev.getType() == TYPE_TAP)
157 plain_packet.setPayloadType(PAYLOAD_TYPE_TAP);
158 else
159 plain_packet.setPayloadType(0);
161 if(param->cl.empty())
162 continue;
163 //std::cout << "got Packet for plain "<<plain_packet.getDstAddr().toString();
164 ConnectionMap::iterator cit;
165 #ifndef NOROUTING
168 mux = gRoutingTable.getRoute(plain_packet.getDstAddr());
169 //std::cout << " -> "<<mux << std::endl;
170 cit = param->cl.getConnection(mux);
172 catch (std::exception& e)
174 continue; // no route
176 #else
177 cit = param->cl.getBegin();
178 #endif
180 if(cit==param->cl.getEnd())
181 continue; //no connection
182 ConnectionParam & conn = cit->second;
184 if(conn.remote_end_ == emptyEndpoint)
186 //cLog.msg(Log::PRIO_INFO) << "no remote address set";
187 continue;
190 // generate packet-key TODO: do this only when needed
191 conn.kd_.generate(LABEL_SATP_ENCRYPTION, conn.seq_nr_, session_key);
192 conn.kd_.generate(LABEL_SATP_SALT, conn.seq_nr_, session_salt);
194 c->setKey(session_key);
195 c->setSalt(session_salt);
197 // encrypt packet
198 c->encrypt(plain_packet, encrypted_packet, conn.seq_nr_, gOpt.getSenderId(), mux);
200 encrypted_packet.setHeader(conn.seq_nr_, gOpt.getSenderId(), mux);
201 conn.seq_nr_++;
203 // add authentication tag
204 if(a->getMaxLength()) {
205 encrypted_packet.addAuthTag();
206 conn.kd_.generate(LABEL_SATP_MSG_AUTH, encrypted_packet.getSeqNr(), session_auth_key);
207 a->setKey(session_auth_key);
208 a->generate(encrypted_packet);
212 param->src.send(encrypted_packet.getBuf(), encrypted_packet.getLength(), conn.remote_end_);
214 catch (std::exception& e)
216 // ignoring icmp port unreachable :) and other socket errors :(
220 catch(std::runtime_error& e)
222 cLog.msg(Log::PRIO_ERR) << "sender thread died due to an uncaught runtime_error: " << e.what();
224 catch(std::exception& e)
226 cLog.msg(Log::PRIO_ERR) << "sender thread died due to an uncaught exception: " << e.what();
230 #ifndef ANYTUN_NOSYNC
231 void syncConnector(void* p )
233 ThreadParam* param = reinterpret_cast<ThreadParam*>(p);
235 SyncClient sc ( param->connto.host, param->connto.port);
236 sc.run();
239 void syncListener(SyncQueue * queue)
243 boost::asio::io_service io_service;
244 SyncTcpConnection::proto::resolver resolver(io_service);
245 SyncTcpConnection::proto::endpoint e;
246 if(gOpt.getLocalSyncAddr()!="")
248 SyncTcpConnection::proto::resolver::query query(gOpt.getLocalSyncAddr(), gOpt.getLocalSyncPort());
249 e = *resolver.resolve(query);
250 } else {
251 SyncTcpConnection::proto::resolver::query query(gOpt.getLocalSyncPort());
252 e = *resolver.resolve(query);
256 SyncServer server(io_service,e);
257 server.onConnect=boost::bind(syncOnConnect,_1);
258 queue->setSyncServerPtr(&server);
259 io_service.run();
261 catch (std::exception& e)
263 std::string addr = gOpt.getLocalSyncAddr() == "" ? "*" : gOpt.getLocalSyncAddr();
264 cLog.msg(Log::PRIO_ERR) << "sync: cannot bind to " << addr << ":" << gOpt.getLocalSyncPort()
265 << " (" << e.what() << ")" << std::endl;
269 #endif
271 void receiver(void* p)
275 ThreadParam* param = reinterpret_cast<ThreadParam*>(p);
277 std::auto_ptr<Cipher> c( CipherFactory::create(gOpt.getCipher()) );
278 std::auto_ptr<AuthAlgo> a( AuthAlgoFactory::create(gOpt.getAuthAlgo()) );
280 EncryptedPacket encrypted_packet(MAX_PACKET_LENGTH);
281 PlainPacket plain_packet(MAX_PACKET_LENGTH);
283 Buffer session_key(u_int32_t(SESSION_KEYLEN_ENCR)); // TODO: hardcoded size
284 Buffer session_salt(u_int32_t(SESSION_KEYLEN_SALT)); // TODO: hardcoded size
285 Buffer session_auth_key(u_int32_t(SESSION_KEYLEN_AUTH)); // TODO: hardcoded size
287 while(1)
289 PacketSourceEndpoint remote_end;
291 plain_packet.setLength(MAX_PACKET_LENGTH);
292 encrypted_packet.withAuthTag(false);
293 encrypted_packet.setLength(MAX_PACKET_LENGTH);
295 // read packet from socket
296 u_int32_t len = param->src.recv(encrypted_packet.getBuf(), encrypted_packet.getLength(), remote_end);
297 encrypted_packet.setLength(len);
299 mux_t mux = encrypted_packet.getMux();
300 // autodetect peer
301 if( param->cl.empty() && gOpt.getRemoteAddr() == "")
303 cLog.msg(Log::PRIO_NOTICE) << "autodetected remote host " << remote_end;
304 createConnection(remote_end, param->cl, gOpt.getSeqWindowSize(),param->queue,mux);
307 ConnectionMap::iterator cit = param->cl.getConnection(mux);
308 if (cit == param->cl.getEnd())
309 continue;
310 ConnectionParam & conn = cit->second;
312 // check whether auth tag is ok or not
313 if(a->getMaxLength()) {
314 encrypted_packet.withAuthTag(true);
315 conn.kd_.generate(LABEL_SATP_MSG_AUTH, encrypted_packet.getSeqNr(), session_auth_key);
316 a->setKey(session_auth_key);
317 if(!a->checkTag(encrypted_packet)) {
318 cLog.msg(Log::PRIO_NOTICE) << "wrong Authentication Tag!" << std::endl;
319 continue;
321 encrypted_packet.removeAuthTag();
324 //Allow dynamic IP changes
325 //TODO: add command line option to turn this off
326 if (remote_end != conn.remote_end_)
328 cLog.msg(Log::PRIO_NOTICE) << "connection "<< mux << " autodetected remote host ip changed " << remote_end;
329 conn.remote_end_=remote_end;
330 SyncCommand sc (param->cl,mux);
331 param->queue.push(sc);
334 // Replay Protection
335 if (!checkPacketSeqNr(encrypted_packet, conn))
336 continue;
338 // generate packet-key
339 conn.kd_.generate(LABEL_SATP_ENCRYPTION, encrypted_packet.getSeqNr(), session_key);
340 conn.kd_.generate(LABEL_SATP_SALT, encrypted_packet.getSeqNr(), session_salt);
341 c->setKey(session_key);
342 c->setSalt(session_salt);
344 // decrypt packet
345 c->decrypt(encrypted_packet, plain_packet);
347 // check payload_type
348 if((param->dev.getType() == TYPE_TUN && plain_packet.getPayloadType() != PAYLOAD_TYPE_TUN4 &&
349 plain_packet.getPayloadType() != PAYLOAD_TYPE_TUN6) ||
350 (param->dev.getType() == TYPE_TAP && plain_packet.getPayloadType() != PAYLOAD_TYPE_TAP))
351 continue;
353 // write it on the device
354 param->dev.write(plain_packet.getPayload(), plain_packet.getLength());
357 catch(std::runtime_error& e)
359 cLog.msg(Log::PRIO_ERR) << "sender thread died due to an uncaught runtime_error: " << e.what();
361 catch(std::exception& e)
363 cLog.msg(Log::PRIO_ERR) << "receiver thread died due to an uncaught exception: " << e.what();
368 int main(int argc, char* argv[])
370 bool daemonized=false;
371 try
374 // std::cout << "anytun - secure anycast tunneling protocol" << std::endl;
375 if(!gOpt.parse(argc, argv)) {
376 gOpt.printUsage();
377 exit(-1);
380 cLog.msg(Log::PRIO_NOTICE) << "anytun started...";
382 std::ofstream pidFile;
383 if(gOpt.getPidFile() != "") {
384 pidFile.open(gOpt.getPidFile().c_str());
385 if(!pidFile.is_open()) {
386 std::cout << "can't open pid file" << std::endl;
390 TunDevice dev(gOpt.getDevName(), gOpt.getDevType(), gOpt.getIfconfigParamLocal(), gOpt.getIfconfigParamRemoteNetmask());
391 cLog.msg(Log::PRIO_NOTICE) << "dev created (opened)";
392 cLog.msg(Log::PRIO_NOTICE) << "dev opened - actual name is '" << dev.getActualName() << "'";
393 cLog.msg(Log::PRIO_NOTICE) << "dev type is '" << dev.getTypeString() << "'";
394 #ifndef NOEXEC
395 if(gOpt.getPostUpScript() != "") {
396 int postup_ret = execScript(gOpt.getPostUpScript(), dev.getActualName());
397 cLog.msg(Log::PRIO_NOTICE) << "post up script '" << gOpt.getPostUpScript() << "' returned " << postup_ret;
399 #endif
401 PacketSource* src;
402 if(gOpt.getLocalAddr() == "")
403 src = new UDPPacketSource(gOpt.getLocalPort());
404 else
405 src = new UDPPacketSource(gOpt.getLocalAddr(), gOpt.getLocalPort());
407 ConnectionList & cl (gConnectionList);
408 ConnectToList connect_to = gOpt.getConnectTo();
409 SyncQueue queue;
411 if(gOpt.getRemoteAddr() != "")
413 boost::asio::io_service io_service;
414 UDPPacketSource::proto::resolver resolver(io_service);
415 UDPPacketSource::proto::resolver::query query(gOpt.getRemoteAddr(), gOpt.getRemotePort());
416 UDPPacketSource::proto::endpoint endpoint = *resolver.resolve(query);
417 createConnection(endpoint,cl,gOpt.getSeqWindowSize(), queue, gOpt.getMux());
420 RouteList routes = gOpt.getRoutes();
421 RouteList::const_iterator rit;
422 for(rit = routes.begin(); rit != routes.end(); ++rit)
424 NetworkAddress addr( rit->net_addr );
425 NetworkPrefix prefix( addr, rit->prefix_length );
426 gRoutingTable.addRoute( prefix, gOpt.getMux() );
428 if (connect_to.begin() == connect_to.end() && routes.begin() == routes.end() && gOpt.getDevType()=="tun")
430 std::cout << "No Routes and no syncronisation hosts have be specified"<< std::endl;
431 std::cout << "anytun won't be able to send any data"<< std::endl;
432 std::cout << "most likely you want to add --route 0.0.0.0/0 --route ::/0"<< std::endl;
433 std::cout << "to your command line to allow both ipv4 and ipv6 traffic"<< std::endl;
434 std::cout << "(this does not set operating system routes, use the post-up script"<< std::endl;
435 std::cout << " to set them)"<< std::endl;
436 return -1;
438 #ifndef NODAEMON
439 if(gOpt.getChroot())
440 chrootAndDrop(gOpt.getChrootDir(), gOpt.getUsername());
441 if(gOpt.getDaemonize())
443 daemonize();
444 daemonized = true;
447 if(pidFile.is_open()) {
448 pid_t pid = getpid();
449 pidFile << pid;
450 pidFile.close();
452 #endif
454 #ifndef NOSIGNALCONTROLLER
455 SignalController sig;
456 sig.init();
457 #endif
459 ThreadParam p(dev, *src, cl, queue,*(new OptionConnectTo()));
461 #ifndef NOCRYPT
462 // this must be called before any other libgcrypt call
463 if(!initLibGCrypt())
464 return -1;
465 #endif
467 boost::thread senderThread(boost::bind(sender,&p));
468 #ifndef NOSIGNALCONTROLLER
469 boost::thread receiverThread(boost::bind(receiver,&p));
470 #endif
471 #ifndef ANYTUN_NOSYNC
472 boost::thread * syncListenerThread;
473 if(gOpt.getLocalSyncPort() != "")
474 syncListenerThread = new boost::thread(boost::bind(syncListener,&queue));
476 std::list<boost::thread *> connectThreads;
477 for(ConnectToList::iterator it = connect_to.begin() ;it != connect_to.end(); ++it) {
478 ThreadParam * point = new ThreadParam(dev, *src, cl, queue,*it);
479 connectThreads.push_back(new boost::thread(boost::bind(syncConnector,point)));
481 #endif
483 #ifndef NOSIGNALCONTROLLER
484 int ret = sig.run();
485 return ret;
486 #else
487 receiver(&p);
488 #endif
489 // TODO cleanup here!
491 pthread_cancel(senderThread);
492 pthread_cancel(receiverThread);
493 #ifndef ANYTUN_NOSYNC
494 if ( gOpt.getLocalSyncPort())
495 pthread_cancel(syncListenerThread);
496 for( std::list<pthread_t>::iterator it = connectThreads.begin() ;it != connectThreads.end(); ++it)
497 pthread_cancel(*it);
498 #endif
500 pthread_join(senderThread, NULL);
501 pthread_join(receiverThread, NULL);
502 #ifndef ANYTUN_NOSYNC
503 if ( gOpt.getLocalSyncPort())
504 pthread_join(syncListenerThread, NULL);
506 for( std::list<pthread_t>::iterator it = connectThreads.begin() ;it != connectThreads.end(); ++it)
507 pthread_join(*it, NULL);
508 #endif
509 delete src;
510 delete &p.connto;
512 return ret;
515 catch(std::runtime_error& e)
517 cLog.msg(Log::PRIO_ERR) << "uncaught runtime error, exiting: " << e.what();
518 if(!daemonized)
519 std::cout << "uncaught runtime error, exiting: " << e.what() << std::endl;
521 catch(std::exception& e)
523 cLog.msg(Log::PRIO_ERR) << "uncaught exception, exiting: " << e.what();
524 if(!daemonized)
525 std::cout << "uncaught exception, exiting: " << e.what() << std::endl;