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/>.
36 #include <boost/bind.hpp>
37 #include <cerrno> // for ENOMEM
39 #include "datatypes.h"
44 #include "plainPacket.h"
45 #include "encryptedPacket.h"
47 #include "keyDerivation.h"
49 #include "cipherFactory.h"
50 #include "authAlgoFactory.h"
51 #include "keyDerivationFactory.h"
52 #include "signalController.h"
54 #include "win32/winService.h"
56 #include "packetSource.h"
57 #include "tunDevice.h"
59 #include "seqWindow.h"
60 #include "connectionList.h"
62 #include "routingTable.h"
63 #include "networkAddress.h"
68 #include "syncQueue.h"
69 #include "syncCommand.h"
70 #include "syncServer.h"
71 #include "syncClient.h"
72 #include "syncOnConnect.hpp"
75 #define MAX_PACKET_LENGTH 1600
77 #include "cryptinit.hpp"
79 #include "sysexec.hpp"
81 bool disableRouting = false;
83 void createConnection(const PacketSourceEndpoint& remote_end, window_size_t seqSize, mux_t mux)
85 SeqWindow* seq = new SeqWindow(seqSize);
87 KeyDerivation * kd = KeyDerivationFactory::create(gOpt.getKdPrf());
88 kd->init(gOpt.getKey(), gOpt.getSalt(), gOpt.getPassphrase());
89 kd->setRole(gOpt.getRole());
90 cLog.msg(Log::PRIO_NOTICE) << "added connection remote host " << remote_end;
92 ConnectionParam connparam ((*kd), (*seq), seq_nr_, remote_end);
93 gConnectionList.addConnection(connparam,mux);
95 SyncCommand sc (gConnectionList,mux);
100 void createConnectionError(const std::exception& e)
102 gSignalController.inject(SIGERROR, e.what());
105 #ifndef ANYTUN_NOSYNC
106 void syncConnector(const OptionHost& connto)
108 SyncClient sc(connto.addr, connto.port);
116 SyncServer server(gOpt.getLocalSyncAddr(), gOpt.getLocalSyncPort(), boost::bind(syncOnConnect, _1));
117 gSyncQueue.setSyncServerPtr(&server);
120 catch(std::runtime_error& e) {
121 cLog.msg(Log::PRIO_ERROR) << "sync listener thread died due to an uncaught runtime_error: " << e.what();
123 catch(std::exception& e) {
124 cLog.msg(Log::PRIO_ERROR) << "sync listener thread died due to an uncaught exception: " << e.what();
129 void sender(TunDevice* dev, PacketSource* src)
132 cLog.msg(Log::PRIO_ERROR) << "sender thread died because either dev or src pointer is null";
138 std::auto_ptr<Cipher> c(CipherFactory::create(gOpt.getCipher(), KD_OUTBOUND));
139 std::auto_ptr<AuthAlgo> a(AuthAlgoFactory::create(gOpt.getAuthAlgo(), KD_OUTBOUND) );
141 PlainPacket plain_packet(MAX_PACKET_LENGTH);
142 EncryptedPacket encrypted_packet(MAX_PACKET_LENGTH, gOpt.getAuthTagLength());
144 u_int16_t mux = gOpt.getMux();
145 PacketSourceEndpoint emptyEndpoint;
147 plain_packet.setLength(MAX_PACKET_LENGTH);
148 encrypted_packet.withAuthTag(false);
149 encrypted_packet.setLength(MAX_PACKET_LENGTH);
151 // read packet from device
152 int len = dev->read(plain_packet.getPayload(), plain_packet.getPayloadLength());
154 continue; // silently ignore device read errors, this is probably no good idea...
156 if(static_cast<u_int32_t>(len) < PlainPacket::getHeaderLength())
157 continue; // ignore short packets
158 plain_packet.setPayloadLength(len);
160 if(dev->getType() == TYPE_TUN)
161 plain_packet.setPayloadType(PAYLOAD_TYPE_TUN);
162 else if(dev->getType() == TYPE_TAP)
163 plain_packet.setPayloadType(PAYLOAD_TYPE_TAP);
165 plain_packet.setPayloadType(0);
167 if(gConnectionList.empty())
169 //std::cout << "got Packet for plain "<<plain_packet.getDstAddr().toString();
170 ConnectionMap::iterator cit;
174 mux = gRoutingTable.getRoute(plain_packet.getDstAddr());
175 //std::cout << " -> "<<mux << std::endl;
176 cit = gConnectionList.getConnection(mux);
177 } catch (std::exception&) { continue; } // no route
179 cit = gConnectionList.getBegin();
181 cit = gConnectionList.getBegin();
184 if(cit==gConnectionList.getEnd())
185 continue; //no connection
186 ConnectionParam & conn = cit->second;
188 if(conn.remote_end_ == emptyEndpoint) {
189 //cLog.msg(Log::PRIO_INFO) << "no remote address set";
194 c->encrypt(conn.kd_, plain_packet, encrypted_packet, conn.seq_nr_, gOpt.getSenderId(), mux);
196 encrypted_packet.setHeader(conn.seq_nr_, gOpt.getSenderId(), mux);
199 // add authentication tag
200 a->generate(conn.kd_, encrypted_packet);
203 src->send(encrypted_packet.getBuf(), encrypted_packet.getLength(), conn.remote_end_);
204 } catch (std::exception& /*e*/) {
205 //TODO: do something here
206 //cLog.msg(Log::PRIO_ERROR) << "could not send data: " << e.what();
210 catch(std::runtime_error& e) {
211 cLog.msg(Log::PRIO_ERROR) << "sender thread died due to an uncaught runtime_error: " << e.what();
213 catch(std::exception& e) {
214 cLog.msg(Log::PRIO_ERROR) << "sender thread died due to an uncaught exception: " << e.what();
218 void receiver(TunDevice* dev, PacketSource* src)
221 cLog.msg(Log::PRIO_ERROR) << "receiver thread died because either dev or src pointer is null";
227 std::auto_ptr<Cipher> c(CipherFactory::create(gOpt.getCipher(), KD_INBOUND));
228 std::auto_ptr<AuthAlgo> a(AuthAlgoFactory::create(gOpt.getAuthAlgo(), KD_INBOUND));
230 EncryptedPacket encrypted_packet(MAX_PACKET_LENGTH, gOpt.getAuthTagLength());
231 PlainPacket plain_packet(MAX_PACKET_LENGTH);
234 PacketSourceEndpoint remote_end;
236 plain_packet.setLength(MAX_PACKET_LENGTH);
237 encrypted_packet.withAuthTag(false);
238 encrypted_packet.setLength(MAX_PACKET_LENGTH);
240 // read packet from socket
243 len = src->recv(encrypted_packet.getBuf(), encrypted_packet.getLength(), remote_end);
244 } catch (std::exception& /*e*/) {
245 //TODO: do something here
246 //cLog.msg(Log::PRIO_ERROR) << "could not recive packet "<< e.what();
250 continue; // silently ignore socket recv errors, this is probably no good idea...
252 if(static_cast<u_int32_t>(len) < EncryptedPacket::getHeaderLength())
253 continue; // ignore short packets
254 encrypted_packet.setLength(len);
256 mux_t mux = encrypted_packet.getMux();
258 if( gConnectionList.empty() && gOpt.getRemoteAddr() == "") {
259 cLog.msg(Log::PRIO_NOTICE) << "autodetected remote host " << remote_end;
260 createConnection(remote_end, gOpt.getSeqWindowSize(),mux);
263 ConnectionMap::iterator cit = gConnectionList.getConnection(mux);
264 if (cit == gConnectionList.getEnd())
266 ConnectionParam & conn = cit->second;
268 // check whether auth tag is ok or not
269 if(!a->checkTag(conn.kd_, encrypted_packet)) {
270 cLog.msg(Log::PRIO_NOTICE) << "wrong Authentication Tag!" << std::endl;
275 if(conn.seq_window_.checkAndAdd(encrypted_packet.getSenderId(), encrypted_packet.getSeqNr())) {
276 cLog.msg(Log::PRIO_NOTICE) << "Replay attack from " << conn.remote_end_
277 << " seq:"<< encrypted_packet.getSeqNr() << " sid: "<< encrypted_packet.getSenderId();
281 //Allow dynamic IP changes
282 //TODO: add command line option to turn this off
283 if (remote_end != conn.remote_end_) {
284 cLog.msg(Log::PRIO_NOTICE) << "connection "<< mux << " autodetected remote host ip changed " << remote_end;
285 conn.remote_end_=remote_end;
286 #ifndef ANYTUN_NOSYNC
287 SyncCommand sc (gConnectionList,mux);
291 // ignore zero length packets
292 if(encrypted_packet.getPayloadLength() <= PlainPacket::getHeaderLength())
296 c->decrypt(conn.kd_, encrypted_packet, plain_packet);
298 // check payload_type
299 if((dev->getType() == TYPE_TUN && plain_packet.getPayloadType() != PAYLOAD_TYPE_TUN4 &&
300 plain_packet.getPayloadType() != PAYLOAD_TYPE_TUN6) ||
301 (dev->getType() == TYPE_TAP && plain_packet.getPayloadType() != PAYLOAD_TYPE_TAP))
304 // write it on the device
305 dev->write(plain_packet.getPayload(), plain_packet.getLength());
308 catch(std::runtime_error& e) {
309 cLog.msg(Log::PRIO_ERROR) << "receiver thread died due to an uncaught runtime_error: " << e.what();
311 catch(std::exception& e) {
312 cLog.msg(Log::PRIO_ERROR) << "receiver thread died due to an uncaught exception: " << e.what();
317 void startSendRecvThreads(PrivInfo& privs, TunDevice* dev, PacketSource* src)
319 void startSendRecvThreads(TunDevice* dev, PacketSource* src)
322 src->waitUntilReady();
325 if(gOpt.getChrootDir() != "") {
327 do_chroot(gOpt.getChrootDir());
329 catch(const std::runtime_error& e) {
330 cLog.msg(Log::PRIO_WARNING) << "ignroing chroot error: " << e.what();
338 boost::thread(boost::bind(sender, dev, src));
339 boost::thread(boost::bind(receiver, dev, src));
345 int main(int argc, char* argv[])
349 if(std::string(argv[1]) == "install") {
350 WinService::install();
353 else if(std::string(argv[1]) == "uninstall") {
354 WinService::uninstall();
361 catch(std::runtime_error& e)
363 std::cout << "caught runtime error, exiting: " << e.what() << std::endl;
365 catch(std::exception& e)
367 std::cout << "caught exception, exiting: " << e.what() << std::endl;
371 int real_main(int argc, char* argv[])
373 int main(int argc, char* argv[])
377 bool daemonized=true;
379 bool daemonized=false;
385 bool result = gOpt.parse(argc, argv);
390 StringList targets = gOpt.getLogTargets();
391 if(targets.empty()) {
393 cLog.addTarget("syslog:3,anytun,daemon");
396 cLog.addTarget("eventlog:3,anytun");
398 cLog.addTarget("stdout:3");
403 StringList::const_iterator it;
404 for(it = targets.begin();it != targets.end(); ++it)
408 catch(syntax_error& e)
410 std::cerr << e << std::endl;
415 cLog.msg(Log::PRIO_NOTICE) << "anytun started...";
416 gOpt.parse_post(); // print warnings
418 // daemonizing has to done before any thread gets started
421 PrivInfo privs(gOpt.getUsername(), gOpt.getGroupname());
423 if(gOpt.getDaemonize()) {
429 // this has to be called before the first thread is started
430 gSignalController.init();
434 #ifndef USE_SSL_CRYPTO
435 // this must be called before any other libgcrypt call
441 OptionNetwork net = gOpt.getIfconfigParam();
442 TunDevice dev(gOpt.getDevName(), gOpt.getDevType(), net.net_addr, net.prefix_length);
443 cLog.msg(Log::PRIO_NOTICE) << "dev opened - name '" << dev.getActualName() << "', node '" << dev.getActualNode() << "'";
444 cLog.msg(Log::PRIO_NOTICE) << "dev type is '" << dev.getTypeString() << "'";
446 if(gOpt.getPostUpScript() != "") {
447 cLog.msg(Log::PRIO_NOTICE) << "executing post-up script '" << gOpt.getPostUpScript() << "'";
448 execScript(gOpt.getPostUpScript(), dev.getActualName(), dev.getActualNode());
452 PacketSource* src = new UDPPacketSource(gOpt.getLocalAddr(), gOpt.getLocalPort());
454 if(gOpt.getRemoteAddr() != "")
455 gResolver.resolveUdp(gOpt.getRemoteAddr(), gOpt.getRemotePort(), boost::bind(createConnection, _1, gOpt.getSeqWindowSize(), gOpt.getMux()), boost::bind(createConnectionError, _1), gOpt.getResolvAddrType());
457 HostList connect_to = gOpt.getRemoteSyncHosts();
459 NetworkList routes = gOpt.getRoutes();
460 NetworkList::const_iterator rit;
461 for(rit = routes.begin(); rit != routes.end(); ++rit) {
462 NetworkAddress addr( rit->net_addr );
463 NetworkPrefix prefix( addr, static_cast<u_int8_t>(rit->prefix_length));
464 gRoutingTable.addRoute( prefix, gOpt.getMux() );
466 if (connect_to.begin() == connect_to.end() || gOpt.getDevType()!="tun") {
467 cLog.msg(Log::PRIO_NOTICE) << "No sync/control host defined or not a tun device. Disabling multi connection support (routing)";
472 #ifndef ANYTUN_NOSYNC
473 boost::thread* syncListenerThread = NULL;
474 if(gOpt.getLocalSyncPort() != "")
475 syncListenerThread = new boost::thread(boost::bind(syncListener));
477 boost::thread_group connectThreads;
478 for(HostList::const_iterator it = connect_to.begin() ;it != connect_to.end(); ++it)
479 connectThreads.create_thread(boost::bind(syncConnector, *it));
482 // wait for packet source to finish in a seperate thread in order
483 // to be still able to process signals while waiting
485 boost::thread(boost::bind(startSendRecvThreads, privs, &dev, src));
487 boost::thread(boost::bind(startSendRecvThreads, &dev, src));
490 #if defined(WIN_SERVICE)
492 gWinService.waitForStop();
494 int ret = gSignalController.run();
497 // TODO: stop all threads and cleanup
504 #if defined(WIN_SERVICE)
509 catch(std::runtime_error& e)
511 cLog.msg(Log::PRIO_ERROR) << "uncaught runtime error, exiting: " << e.what();
513 std::cout << "uncaught runtime error, exiting: " << e.what() << std::endl;
515 catch(std::exception& e)
517 cLog.msg(Log::PRIO_ERROR) << "uncaught exception, exiting: " << e.what();
519 std::cout << "uncaught exception, exiting: " << e.what() << std::endl;
521 #if defined(WIN_SERVICE)