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
36 #include "datatypes.h"
42 #include "keyDerivation.h"
44 //#include "authTag.h"
45 #include "signalController.h"
46 #include "packetSource.h"
47 #include "tunDevice.h"
49 #include "seqWindow.h"
50 #include "connectionList.h"
52 #include "Sockets/SocketHandler.h"
53 #include "syncListenSocket.h"
55 #include "syncSocket.h"
57 #define PAYLOAD_TYPE_TAP 0x6558
58 #define PAYLOAD_TYPE_TUN 0x0800
70 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
71 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
76 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
77 'i', 'j', 'k', 'l', 'm', 'n'
80 void createConnection(const std::string
& remote_host
, u_int16_t remote_port
, ConnectionList
& cl
, u_int16_t seqSize
)
83 SeqWindow
* seq
= new SeqWindow(seqSize
);
85 KeyDerivation
* kd
= new KeyDerivation
;
86 kd
->init(Buffer(key
, sizeof(key
)), Buffer(salt
, sizeof(salt
)));
87 cLog
.msg(Log::PRIO_NOTICE
) << "added connection remote host " << remote_host
<< ":" << remote_port
;
88 ConnectionParam
connparam ( (*kd
), (*seq
), seq_nr_
, remote_host
, remote_port
);
89 cl
.addConnection(connparam
,std::string("default"));
93 void encryptPacket(Packet
& pack
, Cypher
& c
, ConnectionParam
& conn
, void* p
)
95 Param
* param
= reinterpret_cast<Param
*>(p
);
97 Buffer
tmp_key(16), tmp_salt(14);
98 //TODO fix key derivation!
100 conn
.kd_
.generate(label_satp_encryption
, conn
.seq_nr_
, tmp_key
, tmp_key
.getLength());
101 conn
.kd_
.generate(label_satp_salt
, conn
.seq_nr_
, tmp_salt
, tmp_salt
.getLength());
103 // Buffer tmp_key(key, sizeof(key));
104 // Buffer tmp_salt(salt, sizeof(salt));
109 cLog
.msg(Log::PRIO_NOTICE
) << "Send Package: seq: " << conn
.seq_nr_
110 << ", sID: " << param
->opt
.getSenderId();
111 //cLog.msg(Log::PRIO_NOTICE) << "Package dump: " << pack.getHexDump();
113 c
.cypher(pack
, conn
.seq_nr_
, param
->opt
.getSenderId());
116 bool decryptPacket(Packet
& pack
, Cypher
& c
, ConnectionParam
& conn
)
118 u_int16_t sid
= pack
.getSenderId();
119 u_int16_t seq
= pack
.getSeqNr();
123 // decypher the packet
124 Buffer
tmp_key(16), tmp_salt(14);
125 conn
.kd_
.generate(label_satp_encryption
, seq
, tmp_key
, tmp_key
.getLength());
126 conn
.kd_
.generate(label_satp_salt
, seq
, tmp_salt
, tmp_salt
.getLength());
128 // Buffer tmp_key(key, sizeof(key));
129 // Buffer tmp_salt(salt, sizeof(salt));
133 c
.cypher(pack
, seq
, sid
);
135 cLog
.msg(Log::PRIO_NOTICE
) << "Received Package: seq: " << seq
137 //cLog.msg(Log::PRIO_NOTICE) << "Package dump: " << pack.getHexDump();
142 void addPacketAuthTag(Packet
& pack
, Cypher
& c
, ConnectionParam
& conn
)
145 // // calc auth_tag and add it to the packet
146 // AuthTag at = a.calc(pack);
147 // if(at != AuthTag(0)) {
148 // //auth_tag_t at = a.calc(pack);
149 // pack.addAuthTag(at);
152 // send it out to remote host
155 bool checkPacketAuthTag(Packet
& pack
, Cypher
& c
, ConnectionParam
& conn
)
157 // // check auth_tag and remove it
158 // AuthTag at = pack.getAuthTag();
159 pack
.removeAuthTag();
160 //return at == a.calc(pack);
164 bool checkPacketSeqNr(Packet
& pack
,ConnectionParam
& conn
)
166 // u_int16_t sid = pack.getSenderId();
167 // u_int16_t seq = pack.getSeqNr();
168 // compare sender_id and seq with window
169 if(conn
.seq_window_
.hasSeqNr(pack
.getSenderId(), pack
.getSeqNr()))
171 cLog
.msg(Log::PRIO_NOTICE
) << "Replay attack from " << conn
.remote_host_
<<":"<< conn
.remote_port_
<< " seq:"<<pack
.getSeqNr() << " sid: "<<pack
.getSenderId();
175 conn
.seq_window_
.addSeqNr(pack
.getSenderId(), pack
.getSeqNr());
179 void* sender(void* p
)
181 Param
* param
= reinterpret_cast<Param
*>(p
);
182 //TODO make Cypher selectable with command line option
189 //TODO make pack global, reduce dynamic memory!
190 Packet
pack(1600); // fix me... mtu size
192 // read packet from device
193 int len
= param
->dev
.read(pack
);
194 //TODO remove, no dynamic memory resizing
195 pack
.resizeBack(len
);
197 if( param
->cl
.empty())
199 ConnectionParam
& conn
= param
->cl
.getConnection();
201 if(param
->dev
.getType() == TunDevice::TYPE_TUN
)
202 pack
.addPayloadType(PAYLOAD_TYPE_TUN
);
203 else if(param
->dev
.getType() == TunDevice::TYPE_TAP
)
204 pack
.addPayloadType(PAYLOAD_TYPE_TAP
);
206 pack
.addPayloadType(0);
208 encryptPacket(pack
, c
, conn
, param
);
210 pack
.addHeader(conn
.seq_nr_
, param
->opt
.getSenderId());
213 addPacketAuthTag(pack
, c
, conn
);
214 param
->src
.send(pack
, conn
.remote_host_
, conn
.remote_port_
);
219 void* syncConnector(void* p
)
221 Param
* param
= reinterpret_cast<Param
*>(p
);
224 SyncSocket
sock(h
,param
->cl
);
226 sock
.Open( param
->opt
.getRemoteSyncAddr(), param
->opt
.getRemoteSyncPort());
235 void* syncListener(void* p
)
237 Param
* param
= reinterpret_cast<Param
*>(p
);
239 SOCKETS_NAMESPACE::SocketHandler h
;
240 SyncListenSocket
<SyncSocket
,ConnectionList
> l(h
,param
->cl
);
242 if (l
.Bind(param
->opt
.getLocalSyncPort()))
244 Utility::ResolveLocal(); // resolve local hostname
253 void* receiver(void* p
)
255 Param
* param
= reinterpret_cast<Param
*>(p
);
263 u_int16_t remote_port
;
264 // u_int16_t sid = 0, seq = 0;
265 Packet
pack(1600); // fix me... mtu size
267 // read packet from socket
268 u_int32_t len
= param
->src
.recv(pack
, remote_host
, remote_port
);
269 pack
.resizeBack(len
);
270 pack
.withPayloadType(true).withHeader(true).withAuthTag(false);
274 // TODO check auth tag first
275 // this should be done by keymanagement anyway
276 if(param
->opt
.getRemoteAddr() == "" && param
->cl
.empty())
278 cLog
.msg(Log::PRIO_NOTICE
) << "autodetected remote host " << remote_host
<< ":" << remote_port
;
279 createConnection(remote_host
, remote_port
, param
->cl
,param
->opt
.getSeqWindowSize());
282 //TODO Add multi connection support here
283 ConnectionParam
& conn
= param
->cl
.getConnection();
285 if (!checkPacketAuthTag(pack
, c
, conn
))
288 //Allow dynamic IP changes
289 //TODO add command line option to turn this off
290 if (remote_host
!= conn
.remote_host_
|| remote_port
!= conn
.remote_port_
)
292 cLog
.msg(Log::PRIO_NOTICE
) << "autodetected remote host ip changed " << remote_host
<< ":" << remote_port
;
293 conn
.remote_host_
=remote_host
;
294 conn
.remote_port_
=remote_port
;
298 if (!checkPacketSeqNr(pack
,conn
))
301 if (!decryptPacket(pack
, c
, conn
))
303 // check payload_type and remove it
304 if((param
->dev
.getType() == TunDevice::TYPE_TUN
&& pack
.getPayloadType() != PAYLOAD_TYPE_TUN
) ||
305 (param
->dev
.getType() == TunDevice::TYPE_TAP
&& pack
.getPayloadType() != PAYLOAD_TYPE_TAP
))
307 pack
.removePayloadType();
309 // write it on the device
310 param
->dev
.write(pack
);
316 GCRY_THREAD_OPTION_PTHREAD_IMPL
;
319 int main(int argc
, char* argv
[])
321 std::cout
<< "anytun - secure anycast tunneling protocol" << std::endl
;
323 if(!opt
.parse(argc
, argv
))
328 cLog
.msg(Log::PRIO_NOTICE
) << "anytun started...";
330 SignalController sig
;
332 std::string
dev_type(opt
.getDevType());
333 TunDevice
dev(opt
.getDevName().c_str(), dev_type
=="" ? NULL
: dev_type
.c_str(), opt
.getIfconfigParamLocal().c_str(), opt
.getIfconfigParamRemoteNetmask().c_str());
336 if(opt
.getLocalAddr() == "")
337 src
= new UDPPacketSource(opt
.getLocalPort());
339 src
= new UDPPacketSource(opt
.getLocalAddr(), opt
.getLocalPort());
343 if(opt
.getRemoteAddr() != "")
344 createConnection(opt
.getRemoteAddr(),opt
.getRemotePort(),cl
,opt
.getSeqWindowSize());
347 struct Param p
= {opt
, dev
, *src
, cl
};
349 cLog
.msg(Log::PRIO_NOTICE
) << "dev created (opened)";
350 cLog
.msg(Log::PRIO_NOTICE
) << "dev opened - actual name is '" << p
.dev
.getActualName() << "'";
351 cLog
.msg(Log::PRIO_NOTICE
) << "dev type is '" << p
.dev
.getTypeString() << "'";
353 gcry_control( GCRYCTL_SET_THREAD_CBS
, &gcry_threads_pthread
);
355 pthread_t senderThread
;
356 pthread_create(&senderThread
, NULL
, sender
, &p
);
357 pthread_t receiverThread
;
358 pthread_create(&receiverThread
, NULL
, receiver
, &p
);
359 pthread_t syncListenerThread
;
360 pthread_t syncConnectorThread
;
361 if ( opt
.getLocalSyncPort())
362 pthread_create(&syncListenerThread
, NULL
, syncListener
, &p
);
363 if ( opt
.getRemoteSyncPort() && opt
.getRemoteSyncAddr() != "")
364 pthread_create(&syncConnectorThread
, NULL
, syncConnector
, &p
);
368 pthread_cancel(senderThread
);
369 pthread_cancel(receiverThread
);
370 if ( opt
.getLocalSyncPort())
371 pthread_cancel(syncListenerThread
);
372 if ( opt
.getRemoteSyncPort() && opt
.getRemoteSyncAddr() != "")
373 pthread_cancel(syncConnectorThread
);
374 pthread_join(senderThread
, NULL
);
375 pthread_join(receiverThread
, NULL
);
376 if ( opt
.getLocalSyncPort())
377 pthread_join(syncListenerThread
, NULL
);
378 if ( opt
.getRemoteSyncPort() && opt
.getRemoteSyncAddr() != "")
379 pthread_join(syncConnectorThread
, NULL
);