got rid of NOPACKED (struct alignment works now under Windows)
[anytun.git] / src / anytun.cpp
blob8c7c23942aeac17bfba2873b8ef1ec646b60a451
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 #include <cerrno> // for ENOMEM
39 #include "datatypes.h"
41 #include "log.h"
42 #include "buffer.h"
43 #include "plainPacket.h"
44 #include "encryptedPacket.h"
45 #include "cipher.h"
46 #include "keyDerivation.h"
47 #include "authAlgo.h"
48 #include "cipherFactory.h"
49 #include "authAlgoFactory.h"
50 #include "keyDerivationFactory.h"
51 #ifndef NOSIGNALCONTROLLER
52 #include "signalController.h"
53 #endif
54 #include "packetSource.h"
55 #include "tunDevice.h"
56 #include "options.h"
57 #include "seqWindow.h"
58 #include "connectionList.h"
59 #ifndef NOROUTING
60 #include "routingTable.h"
61 #include "networkAddress.h"
62 #endif
65 #ifndef ANYTUN_NOSYNC
66 #include "syncQueue.h"
67 #include "syncCommand.h"
68 #include "syncServer.h"
69 #include "syncClient.h"
70 #include "syncOnConnect.hpp"
71 #endif
73 #include "threadParam.h"
74 #define MAX_PACKET_LENGTH 1600
76 #include "cryptinit.hpp"
77 #include "daemon.hpp"
78 #include "sysexec.hpp"
80 void createConnection(const PacketSourceEndpoint & remote_end, window_size_t seqSize, mux_t mux)
82 SeqWindow* seq = new SeqWindow(seqSize);
83 seq_nr_t seq_nr_=0;
84 KeyDerivation * kd = KeyDerivationFactory::create(gOpt.getKdPrf());
85 kd->init(gOpt.getKey(), gOpt.getSalt());
86 kd->setLogKDRate(gOpt.getLdKdr());
87 cLog.msg(Log::PRIO_NOTICE) << "added connection remote host " << remote_end;
89 ConnectionParam connparam ((*kd), (*seq), seq_nr_, remote_end);
90 gConnectionList.addConnection(connparam,mux);
91 #ifndef ANYTUN_NOSYNC
92 SyncCommand sc (gConnectionList,mux);
93 gSyncQueue.push(sc);
94 #endif
95 #ifndef NOROUTING
96 if (gOpt.getIfconfigParamRemoteNetmask() != "")
98 NetworkAddress addr(gOpt.getIfconfigParamRemoteNetmask());
99 NetworkPrefix prefix(addr,128);
100 gRoutingTable.addRoute(prefix,mux);
101 #ifndef ANYTUN_NOSYNC
102 SyncCommand sc2 (prefix);
103 gSyncQueue.push(sc2);
104 #endif
106 #endif
109 #ifndef ANYTUN_NOSYNC
110 void syncConnector(void* p )
112 ThreadParam* param = reinterpret_cast<ThreadParam*>(p);
114 SyncClient sc ( param->connto.host, param->connto.port);
115 sc.run();
118 void syncListener(SyncQueue * queue)
122 boost::asio::io_service io_service;
123 SyncTcpConnection::proto::resolver resolver(io_service);
124 SyncTcpConnection::proto::endpoint e;
125 if(gOpt.getLocalSyncAddr()!="")
127 SyncTcpConnection::proto::resolver::query query(gOpt.getLocalSyncAddr(), gOpt.getLocalSyncPort());
128 e = *resolver.resolve(query);
129 } else {
130 SyncTcpConnection::proto::resolver::query query(gOpt.getLocalSyncPort());
131 e = *resolver.resolve(query);
135 SyncServer server(io_service,e);
136 server.onConnect=boost::bind(syncOnConnect,_1);
137 queue->setSyncServerPtr(&server);
138 io_service.run();
140 catch (std::exception& e)
142 std::string addr = gOpt.getLocalSyncAddr() == "" ? "*" : gOpt.getLocalSyncAddr();
143 cLog.msg(Log::PRIO_ERR) << "sync: cannot bind to " << addr << ":" << gOpt.getLocalSyncPort()
144 << " (" << e.what() << ")" << std::endl;
148 #endif
150 void sender(void* p)
152 try
154 ThreadParam* param = reinterpret_cast<ThreadParam*>(p);
156 std::auto_ptr<Cipher> c(CipherFactory::create(gOpt.getCipher(), KD_OUTBOUND));
157 std::auto_ptr<AuthAlgo> a(AuthAlgoFactory::create(gOpt.getAuthAlgo(), KD_OUTBOUND) );
159 PlainPacket plain_packet(MAX_PACKET_LENGTH);
160 EncryptedPacket encrypted_packet(MAX_PACKET_LENGTH);
162 u_int16_t mux = gOpt.getMux();
163 PacketSourceEndpoint emptyEndpoint;
164 while(1)
166 plain_packet.setLength(MAX_PACKET_LENGTH);
167 encrypted_packet.withAuthTag(false);
168 encrypted_packet.setLength(MAX_PACKET_LENGTH);
170 // read packet from device
171 u_int32_t len = param->dev.read(plain_packet.getPayload(), plain_packet.getPayloadLength());
172 plain_packet.setPayloadLength(len);
173 // set payload type
174 if(param->dev.getType() == TYPE_TUN)
175 plain_packet.setPayloadType(PAYLOAD_TYPE_TUN);
176 else if(param->dev.getType() == TYPE_TAP)
177 plain_packet.setPayloadType(PAYLOAD_TYPE_TAP);
178 else
179 plain_packet.setPayloadType(0);
181 if(gConnectionList.empty())
182 continue;
183 //std::cout << "got Packet for plain "<<plain_packet.getDstAddr().toString();
184 ConnectionMap::iterator cit;
185 #ifndef NOROUTING
188 mux = gRoutingTable.getRoute(plain_packet.getDstAddr());
189 //std::cout << " -> "<<mux << std::endl;
190 cit = gConnectionList.getConnection(mux);
192 catch (std::exception& e)
194 continue; // no route
196 #else
197 cit = gConnectionList.getBegin();
198 #endif
200 if(cit==gConnectionList.getEnd())
201 continue; //no connection
202 ConnectionParam & conn = cit->second;
204 if(conn.remote_end_ == emptyEndpoint)
206 //cLog.msg(Log::PRIO_INFO) << "no remote address set";
207 continue;
210 // encrypt packet
211 c->encrypt(conn.kd_, plain_packet, encrypted_packet, conn.seq_nr_, gOpt.getSenderId(), mux);
213 encrypted_packet.setHeader(conn.seq_nr_, gOpt.getSenderId(), mux);
214 conn.seq_nr_++;
216 // add authentication tag
217 a->generate(conn.kd_, encrypted_packet);
221 param->src.send(encrypted_packet.getBuf(), encrypted_packet.getLength(), conn.remote_end_);
223 catch (std::exception& e)
225 // ignoring icmp port unreachable :) and other socket errors :(
229 catch(std::runtime_error& e)
231 cLog.msg(Log::PRIO_ERR) << "sender thread died due to an uncaught runtime_error: " << e.what();
233 catch(std::exception& e)
235 cLog.msg(Log::PRIO_ERR) << "sender thread died due to an uncaught exception: " << e.what();
239 void receiver(void* p)
243 ThreadParam* param = reinterpret_cast<ThreadParam*>(p);
245 std::auto_ptr<Cipher> c( CipherFactory::create(gOpt.getCipher(), KD_INBOUND) );
246 std::auto_ptr<AuthAlgo> a( AuthAlgoFactory::create(gOpt.getAuthAlgo(), KD_INBOUND) );
248 EncryptedPacket encrypted_packet(MAX_PACKET_LENGTH);
249 PlainPacket plain_packet(MAX_PACKET_LENGTH);
251 while(1)
253 PacketSourceEndpoint remote_end;
255 plain_packet.setLength(MAX_PACKET_LENGTH);
256 encrypted_packet.withAuthTag(false);
257 encrypted_packet.setLength(MAX_PACKET_LENGTH);
259 // read packet from socket
260 u_int32_t len = param->src.recv(encrypted_packet.getBuf(), encrypted_packet.getLength(), remote_end);
261 encrypted_packet.setLength(len);
263 mux_t mux = encrypted_packet.getMux();
264 // autodetect peer
265 if( gConnectionList.empty() && gOpt.getRemoteAddr() == "")
267 cLog.msg(Log::PRIO_NOTICE) << "autodetected remote host " << remote_end;
268 createConnection(remote_end, gOpt.getSeqWindowSize(),mux);
271 ConnectionMap::iterator cit = gConnectionList.getConnection(mux);
272 if (cit == gConnectionList.getEnd())
273 continue;
274 ConnectionParam & conn = cit->second;
276 // check whether auth tag is ok or not
277 if(!a->checkTag(conn.kd_, encrypted_packet)) {
278 cLog.msg(Log::PRIO_NOTICE) << "wrong Authentication Tag!" << std::endl;
279 continue;
282 //Allow dynamic IP changes
283 //TODO: add command line option to turn this off
284 if (remote_end != conn.remote_end_)
286 cLog.msg(Log::PRIO_NOTICE) << "connection "<< mux << " autodetected remote host ip changed " << remote_end;
287 conn.remote_end_=remote_end;
288 #ifndef ANYTUN_NOSYNC
289 SyncCommand sc (gConnectionList,mux);
290 gSyncQueue.push(sc);
291 #endif
294 // Replay Protection
295 if(conn.seq_window_.checkAndAdd(encrypted_packet.getSenderId(), encrypted_packet.getSeqNr()))
297 cLog.msg(Log::PRIO_NOTICE) << "Replay attack from " << conn.remote_end_
298 << " seq:"<< encrypted_packet.getSeqNr() << " sid: "<< encrypted_packet.getSenderId();
299 continue;
302 // decrypt packet
303 c->decrypt(conn.kd_, encrypted_packet, plain_packet);
305 // check payload_type
306 if((param->dev.getType() == TYPE_TUN && plain_packet.getPayloadType() != PAYLOAD_TYPE_TUN4 &&
307 plain_packet.getPayloadType() != PAYLOAD_TYPE_TUN6) ||
308 (param->dev.getType() == TYPE_TAP && plain_packet.getPayloadType() != PAYLOAD_TYPE_TAP))
309 continue;
311 // write it on the device
312 param->dev.write(plain_packet.getPayload(), plain_packet.getLength());
315 catch(std::runtime_error& e)
317 cLog.msg(Log::PRIO_ERR) << "sender thread died due to an uncaught runtime_error: " << e.what();
319 catch(std::exception& e)
321 cLog.msg(Log::PRIO_ERR) << "receiver thread died due to an uncaught exception: " << e.what();
326 int main(int argc, char* argv[])
328 bool daemonized=false;
329 try
331 cLog.msg(Log::PRIO_NOTICE) << "anytun started...";
332 /// std::cout << "anytun - secure anycast tunneling protocol" << std::endl;
333 int32_t result = gOpt.parse(argc, argv);
334 if(result) {
335 if(result > 0) {
336 std::cerr << "syntax error near: " << argv[result] << std::endl << std::endl;
337 cLog.msg(Log::PRIO_ERR) << "syntax error, exitting";
339 if(result == -2) {
340 std::cerr << "can't parse host-port definition" << std::endl << std::endl;
341 cLog.msg(Log::PRIO_ERR) << "can't parse host-port definition, exitting";
344 gOpt.printUsage();
346 exit(result);
349 std::ofstream pidFile;
350 if(gOpt.getPidFile() != "") {
351 pidFile.open(gOpt.getPidFile().c_str());
352 if(!pidFile.is_open()) {
353 std::cout << "can't open pid file" << std::endl;
357 #ifndef NOCRYPT
358 #ifndef USE_SSL_CRYPTO
359 // this must be called before any other libgcrypt call
360 if(!initLibGCrypt())
361 return -1;
362 #endif
363 #endif
365 TunDevice dev(gOpt.getDevName(), gOpt.getDevType(), gOpt.getIfconfigParamLocal(), gOpt.getIfconfigParamRemoteNetmask());
366 cLog.msg(Log::PRIO_NOTICE) << "dev created (opened)";
367 cLog.msg(Log::PRIO_NOTICE) << "dev opened - actual name is '" << dev.getActualName() << "'";
368 cLog.msg(Log::PRIO_NOTICE) << "dev type is '" << dev.getTypeString() << "'";
369 #ifndef NOEXEC
370 if(gOpt.getPostUpScript() != "") {
371 int postup_ret = execScript(gOpt.getPostUpScript(), dev.getActualName());
372 cLog.msg(Log::PRIO_NOTICE) << "post up script '" << gOpt.getPostUpScript() << "' returned " << postup_ret;
374 #endif
376 PacketSource* src;
377 if(gOpt.getLocalAddr() == "")
378 src = new UDPPacketSource(gOpt.getLocalPort());
379 else
380 src = new UDPPacketSource(gOpt.getLocalAddr(), gOpt.getLocalPort());
382 ConnectToList connect_to = gOpt.getConnectTo();
383 SyncQueue queue;
385 if(gOpt.getRemoteAddr() != "")
387 boost::asio::io_service io_service;
388 UDPPacketSource::proto::resolver resolver(io_service);
389 UDPPacketSource::proto::resolver::query query(gOpt.getRemoteAddr(), gOpt.getRemotePort());
390 UDPPacketSource::proto::endpoint endpoint = *resolver.resolve(query);
391 createConnection(endpoint,gOpt.getSeqWindowSize(), gOpt.getMux());
394 RouteList routes = gOpt.getRoutes();
395 RouteList::const_iterator rit;
396 for(rit = routes.begin(); rit != routes.end(); ++rit)
398 NetworkAddress addr( rit->net_addr );
399 NetworkPrefix prefix( addr, static_cast<u_int8_t>(rit->prefix_length));
400 gRoutingTable.addRoute( prefix, gOpt.getMux() );
402 if (connect_to.begin() == connect_to.end() && routes.begin() == routes.end() && gOpt.getDevType()=="tun")
404 std::cout << "No Routes and no syncronisation hosts have be specified"<< std::endl;
405 std::cout << "anytun won't be able to send any data"<< std::endl;
406 std::cout << "most likely you want to add --route 0.0.0.0/0 --route ::/0"<< std::endl;
407 std::cout << "to your command line to allow both ipv4 and ipv6 traffic"<< std::endl;
408 std::cout << "(this does not set operating system routes, use the post-up script"<< std::endl;
409 std::cout << " to set them)"<< std::endl;
410 return -1;
412 #ifndef NODAEMON
413 if(gOpt.getChroot())
414 chrootAndDrop(gOpt.getChrootDir(), gOpt.getUsername());
415 if(gOpt.getDaemonize())
417 daemonize();
418 daemonized = true;
421 if(pidFile.is_open()) {
422 pid_t pid = getpid();
423 pidFile << pid;
424 pidFile.close();
426 #endif
428 #ifndef NOSIGNALCONTROLLER
429 SignalController sig;
430 sig.init();
431 #endif
433 OptionConnectTo* connTo = new OptionConnectTo();
434 ThreadParam p(dev, *src, *connTo);
436 boost::thread senderThread(boost::bind(sender,&p));
437 #ifndef NOSIGNALCONTROLLER
438 boost::thread receiverThread(boost::bind(receiver,&p));
439 #endif
440 #ifndef ANYTUN_NOSYNC
441 boost::thread * syncListenerThread;
442 if(gOpt.getLocalSyncPort() != "")
443 syncListenerThread = new boost::thread(boost::bind(syncListener,&queue));
445 std::list<boost::thread *> connectThreads;
446 for(ConnectToList::iterator it = connect_to.begin() ;it != connect_to.end(); ++it) {
447 ThreadParam * point = new ThreadParam(dev, *src, *it);
448 connectThreads.push_back(new boost::thread(boost::bind(syncConnector,point)));
450 #endif
452 #ifndef NOSIGNALCONTROLLER
453 int ret = sig.run();
454 #else
455 receiver(&p);
456 int ret = 0;
457 #endif
458 // TODO cleanup threads here!
460 pthread_cancel(senderThread);
461 pthread_cancel(receiverThread);
462 #ifndef ANYTUN_NOSYNC
463 if ( gOpt.getLocalSyncPort())
464 pthread_cancel(syncListenerThread);
465 for( std::list<pthread_t>::iterator it = connectThreads.begin() ;it != connectThreads.end(); ++it)
466 pthread_cancel(*it);
467 #endif
469 pthread_join(senderThread, NULL);
470 pthread_join(receiverThread, NULL);
471 #ifndef ANYTUN_NOSYNC
472 if ( gOpt.getLocalSyncPort())
473 pthread_join(syncListenerThread, NULL);
475 for( std::list<pthread_t>::iterator it = connectThreads.begin() ;it != connectThreads.end(); ++it)
476 pthread_join(*it, NULL);
477 #endif
478 if(src)
479 delete src;
480 if(connTo)
481 delete connTo;
483 return ret;
485 catch(std::runtime_error& e)
487 cLog.msg(Log::PRIO_ERR) << "uncaught runtime error, exiting: " << e.what();
488 #ifndef LOGSTDOUT
489 if(!daemonized)
490 std::cout << "uncaught runtime error, exiting: " << e.what() << std::endl;
491 #endif
493 catch(std::exception& e)
495 cLog.msg(Log::PRIO_ERR) << "uncaught exception, exiting: " << e.what();
496 #ifndef LOGSTDOUT
497 if(!daemonized)
498 std::cout << "uncaught exception, exiting: " << e.what() << std::endl;
499 #endif