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 anytun.org <satp@wirdorange.org>
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License version 2
18 * as published by the Free Software Foundation.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program (see the file COPYING included with this
27 * distribution); if not, write to the Free Software Foundation, Inc.,
28 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
35 #include <cerrno> // for ENOMEM
37 #include "datatypes.h"
41 #include "plainPacket.h"
42 #include "encryptedPacket.h"
44 #include "keyDerivation.h"
47 #include "cipherFactory.h"
48 #include "authAlgoFactory.h"
49 #include "keyDerivationFactory.h"
50 #include "signalController.h"
51 #include "packetSource.h"
52 #include "tunDevice.h"
54 #include "seqWindow.h"
55 #include "connectionList.h"
57 #include "syncQueue.h"
58 #include "syncSocketHandler.h"
59 #include "syncListenSocket.h"
61 #include "syncSocket.h"
62 #include "syncClientSocket.h"
63 #include "syncCommand.h"
65 #include "threadParam.h"
67 #define PAYLOAD_TYPE_TAP 0x6558
68 #define PAYLOAD_TYPE_TUN 0x0800
70 #define MAX_PACKET_LENGTH 1600
72 #define SESSION_KEYLEN_AUTH 20 // TODO: hardcoded size
73 #define SESSION_KEYLEN_ENCR 16 // TODO: hardcoded size
74 #define SESSION_KEYLEN_SALT 14 // TODO: hardcoded size
76 void createConnection(const std::string
& remote_host
, u_int16_t remote_port
, ConnectionList
& cl
, u_int16_t seqSize
, SyncQueue
& queue
)
78 // TODO: use key exchange for master key/salt
80 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
81 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'
85 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
86 'i', 'j', 'k', 'l', 'm', 'n'
89 SeqWindow
* seq
= new SeqWindow(seqSize
);
91 KeyDerivation
* kd
= KeyDerivationFactory::create(gOpt
.getKdPrf());
92 kd
->init(Buffer(key
, sizeof(key
)), Buffer(salt
, sizeof(salt
)));
93 cLog
.msg(Log::PRIO_NOTICE
) << "added connection remote host " << remote_host
<< ":" << remote_port
;
94 ConnectionParam
connparam ( (*kd
), (*seq
), seq_nr_
, remote_host
, remote_port
);
95 cl
.addConnection(connparam
,0);
96 SyncCommand
sc (cl
,0);
101 void addPacketAuthTag(EncryptedPacket
& pack
, AuthAlgo
* a
, ConnectionParam
& conn
)
103 AuthTag at
= a
->calc(pack
);
104 pack
.setAuthTag( at
);
107 bool checkPacketAuthTag(EncryptedPacket
& pack
, AuthAlgo
* a
, ConnectionParam
& conn
)
109 // check auth_tag and remove it
110 AuthTag at
= pack
.getAuthTag();
111 return (at
== a
->calc(pack
));
114 bool checkPacketSeqNr(EncryptedPacket
& pack
,ConnectionParam
& conn
)
116 // compare sender_id and seq with window
117 if(conn
.seq_window_
.hasSeqNr(pack
.getSenderId(), pack
.getSeqNr()))
119 cLog
.msg(Log::PRIO_NOTICE
) << "Replay attack from " << conn
.remote_host_
<<":"<< conn
.remote_port_
120 << " seq:"<<pack
.getSeqNr() << " sid: "<<pack
.getSenderId();
124 conn
.seq_window_
.addSeqNr(pack
.getSenderId(), pack
.getSeqNr());
128 void* sender(void* p
)
130 ThreadParam
* param
= reinterpret_cast<ThreadParam
*>(p
);
132 std::auto_ptr
<Cipher
> c(CipherFactory::create(gOpt
.getCipher()));
133 // std::auto_ptr<AuthAlgo> a(AuthAlgoFactory::create(gOpt.getAuthAlgo()) );
135 PlainPacket
plain_packet(MAX_PACKET_LENGTH
);
136 EncryptedPacket
encrypted_packet(MAX_PACKET_LENGTH
);
138 Buffer
session_key(u_int32_t(SESSION_KEYLEN_ENCR
)); // TODO: hardcoded size
139 Buffer
session_salt(u_int32_t(SESSION_KEYLEN_SALT
)); // TODO: hardcoded size
140 Buffer
session_auth_key(u_int32_t(SESSION_KEYLEN_AUTH
)); // TODO: hardcoded size
146 plain_packet
.setLength(MAX_PACKET_LENGTH
);
147 encrypted_packet
.setLength(MAX_PACKET_LENGTH
);
148 // read packet from device
149 u_int32_t len
= param
->dev
.read(plain_packet
.getPayload(), plain_packet
.getPayloadLength());
150 plain_packet
.setPayloadLength(len
);
152 std::cout
<< "plain_packet.getPayloadLength() = " << plain_packet
.getPayloadLength() << std::endl
;
154 if(param
->cl
.empty())
157 ConnectionMap::iterator cit
= param
->cl
.getConnection(mux
);
158 if(cit
==param
->cl
.getEnd())
160 ConnectionParam
& conn
= cit
->second
;
163 if(param
->dev
.getType() == TunDevice::TYPE_TUN
)
164 plain_packet
.setPayloadType(PAYLOAD_TYPE_TUN
);
165 else if(param
->dev
.getType() == TunDevice::TYPE_TAP
)
166 plain_packet
.setPayloadType(PAYLOAD_TYPE_TAP
);
168 plain_packet
.setPayloadType(0);
170 // generate packet-key
171 conn
.kd_
.generate(LABEL_SATP_ENCRYPTION
, conn
.seq_nr_
, session_key
);
172 conn
.kd_
.generate(LABEL_SATP_SALT
, conn
.seq_nr_
, session_salt
);
174 std::cout
<< "session_key: ";
175 std::cout
<< session_key
.getHexDump();
176 std::cout
<< "session_salt: ";
177 std::cout
<< session_salt
.getHexDump() << std::endl
;
180 c
->setKey(session_key
);
181 c
->setSalt(session_salt
);
184 c
->encrypt(plain_packet
, encrypted_packet
, conn
.seq_nr_
, gOpt
.getSenderId());
186 encrypted_packet
.setHeader(conn
.seq_nr_
, gOpt
.getSenderId(), mux
);
189 // TODO: activate authentication
190 // conn.kd_.generate(LABEL_SATP_MSG_AUTH, encrypted_packet.getSeqNr(), session_auth_key);
191 // a->setKey(session_auth_key);
192 // addPacketAuthTag(encrypted_packet, a.get(), conn);
194 std::cout
<< "encrypted_packet.getLength() = " << encrypted_packet
.getLength() << std::endl
<< std::endl
;
196 param
->src
.send(encrypted_packet
.getBuf(), encrypted_packet
.getLength(), conn
.remote_host_
, conn
.remote_port_
);
201 void* syncConnector(void* p
)
203 ThreadParam
* param
= reinterpret_cast<ThreadParam
*>(p
);
206 SyncClientSocket
sock(h
,param
->cl
);
208 sock
.Open( param
->connto
.host
, param
->connto
.port
);
217 void* syncListener(void* p
)
219 ThreadParam
* param
= reinterpret_cast<ThreadParam
*>(p
);
221 SyncSocketHandler
h(param
->queue
);
222 SyncListenSocket
<SyncSocket
,ConnectionList
> l(h
,param
->cl
);
224 if (l
.Bind(gOpt
.getLocalSyncPort()))
227 Utility::ResolveLocal(); // resolve local hostname
235 void* receiver(void* p
)
237 ThreadParam
* param
= reinterpret_cast<ThreadParam
*>(p
);
239 std::auto_ptr
<Cipher
> c( CipherFactory::create(gOpt
.getCipher()) );
240 // std::auto_ptr<AuthAlgo> a( AuthAlgoFactory::create(gOpt.getAuthAlgo()) );
242 EncryptedPacket
encrypted_packet(MAX_PACKET_LENGTH
);
243 PlainPacket
plain_packet(MAX_PACKET_LENGTH
);
245 Buffer
session_key(u_int32_t(SESSION_KEYLEN_ENCR
)); // TODO: hardcoded size
246 Buffer
session_salt(u_int32_t(SESSION_KEYLEN_SALT
)); // TODO: hardcoded size
247 Buffer
session_auth_key(u_int32_t(SESSION_KEYLEN_AUTH
)); // TODO: hardcoded size
252 u_int16_t remote_port
;
254 plain_packet
.setLength(MAX_PACKET_LENGTH
);
255 encrypted_packet
.setLength(MAX_PACKET_LENGTH
);
257 // read packet from socket
258 u_int32_t len
= param
->src
.recv(encrypted_packet
.getBuf(), encrypted_packet
.getLength(), remote_host
, remote_port
);
259 encrypted_packet
.setLength(len
);
261 // TODO: check auth tag first
262 // conn.kd_.generate(LABEL_SATP_MSG_AUTH, encrypted_packet.getSeqNr(), session_auth_key);
263 // a->setKey( session_auth_key );
264 // if(!checkPacketAuthTag(encrypted_packet, a.get(), conn))
269 if(gOpt
.getRemoteAddr() == "" && param
->cl
.empty())
271 cLog
.msg(Log::PRIO_NOTICE
) << "autodetected remote host " << remote_host
<< ":" << remote_port
;
272 createConnection(remote_host
, remote_port
, param
->cl
, gOpt
.getSeqWindowSize(),param
->queue
);
275 // TODO: Add multi connection support here
276 ConnectionParam
& conn
= param
->cl
.getConnection(0)->second
;
278 //Allow dynamic IP changes
279 //TODO: add command line option to turn this off
280 if (remote_host
!= conn
.remote_host_
|| remote_port
!= conn
.remote_port_
)
282 cLog
.msg(Log::PRIO_NOTICE
) << "autodetected remote host ip changed " << remote_host
<< ":" << remote_port
;
283 conn
.remote_host_
=remote_host
;
284 conn
.remote_port_
=remote_port
;
285 SyncCommand
sc (param
->cl
,0);
286 param
->queue
.push(sc
);
290 if (!checkPacketSeqNr(encrypted_packet
, conn
))
293 // generate packet-key
294 conn
.kd_
.generate(LABEL_SATP_ENCRYPTION
, encrypted_packet
.getSeqNr(), session_key
);
295 conn
.kd_
.generate(LABEL_SATP_SALT
, encrypted_packet
.getSeqNr(), session_salt
);
296 c
->setKey(session_key
);
297 c
->setSalt(session_salt
);
300 c
->decrypt(encrypted_packet
, plain_packet
);
302 // check payload_type
303 if((param
->dev
.getType() == TunDevice::TYPE_TUN
&& plain_packet
.getPayloadType() != PAYLOAD_TYPE_TUN
) ||
304 (param
->dev
.getType() == TunDevice::TYPE_TAP
&& plain_packet
.getPayloadType() != PAYLOAD_TYPE_TAP
))
307 // write it on the device
308 param
->dev
.write(plain_packet
.getPayload(), plain_packet
.getLength());
313 #define MIN_GCRYPT_VERSION "1.2.3"
314 // make libgcrypt thread safe
316 GCRY_THREAD_OPTION_PTHREAD_IMPL
;
321 // make libgcrypt thread safe
322 // this must be called before any other libgcrypt call
323 gcry_control( GCRYCTL_SET_THREAD_CBS
, &gcry_threads_pthread
);
325 // this must be called right after the GCRYCTL_SET_THREAD_CBS command
326 // no other function must be called till now
327 if( !gcry_check_version( MIN_GCRYPT_VERSION
) ) {
328 std::cout
<< "initLibGCrypt: Invalid Version of libgcrypt, should be >= " << MIN_GCRYPT_VERSION
<< std::endl
;
332 // Tell Libgcrypt that initialization has completed.
333 gcry_error_t err
= gcry_control(GCRYCTL_INITIALIZATION_FINISHED
);
335 std::cout
<< "initLibGCrypt: Failed to finish the initialization of libgcrypt: " << gpg_strerror( err
) << std::endl
;
339 cLog
.msg(Log::PRIO_NOTICE
) << "initLibGCrypt: libgcrypt init finished";
343 int main(int argc
, char* argv
[])
345 std::cout
<< "anytun - secure anycast tunneling protocol" << std::endl
;
346 if(!gOpt
.parse(argc
, argv
))
351 cLog
.msg(Log::PRIO_NOTICE
) << "anytun started...";
353 SignalController sig
;
355 std::string
dev_type(gOpt
.getDevType());
356 TunDevice
dev(gOpt
.getDevName().c_str(), dev_type
=="" ? NULL
: dev_type
.c_str(), gOpt
.getIfconfigParamLocal().c_str(), gOpt
.getIfconfigParamRemoteNetmask().c_str());
359 if(gOpt
.getLocalAddr() == "")
360 src
= new UDPPacketSource(gOpt
.getLocalPort());
362 src
= new UDPPacketSource(gOpt
.getLocalAddr(), gOpt
.getLocalPort());
365 ConnectToList connect_to
= gOpt
.getConnectTo();
368 if(gOpt
.getRemoteAddr() != "")
369 createConnection(gOpt
.getRemoteAddr(),gOpt
.getRemotePort(),cl
,gOpt
.getSeqWindowSize(), queue
);
371 ThreadParam
p(dev
, *src
, cl
, queue
,*(new OptionConnectTo()));
373 cLog
.msg(Log::PRIO_NOTICE
) << "dev created (opened)";
374 cLog
.msg(Log::PRIO_NOTICE
) << "dev opened - actual name is '" << p
.dev
.getActualName() << "'";
375 cLog
.msg(Log::PRIO_NOTICE
) << "dev type is '" << p
.dev
.getTypeString() << "'";
377 // this must be called before any other libgcrypt call
381 pthread_t senderThread
;
382 pthread_create(&senderThread
, NULL
, sender
, &p
);
383 pthread_t receiverThread
;
384 pthread_create(&receiverThread
, NULL
, receiver
, &p
);
386 pthread_t syncListenerThread
;
387 if ( gOpt
.getLocalSyncPort())
388 pthread_create(&syncListenerThread
, NULL
, syncListener
, &p
);
390 std::list
<pthread_t
> connectThreads
;
391 for(ConnectToList::iterator it
= connect_to
.begin() ;it
!= connect_to
.end(); ++it
)
393 connectThreads
.push_back(pthread_t());
394 ThreadParam
* point
= new ThreadParam(dev
, *src
, cl
, queue
,*it
);
395 pthread_create(& connectThreads
.back(), NULL
, syncConnector
, point
);
400 pthread_cancel(senderThread
);
401 pthread_cancel(receiverThread
);
402 if ( gOpt
.getLocalSyncPort())
403 pthread_cancel(syncListenerThread
);
404 for( std::list
<pthread_t
>::iterator it
= connectThreads
.begin() ;it
!= connectThreads
.end(); ++it
)
407 pthread_join(senderThread
, NULL
);
408 pthread_join(receiverThread
, NULL
);
409 if ( gOpt
.getLocalSyncPort())
410 pthread_join(syncListenerThread
, NULL
);
412 for( std::list
<pthread_t
>::iterator it
= connectThreads
.begin() ;it
!= connectThreads
.end(); ++it
)
413 pthread_join(*it
, NULL
);