A Discrete-Event Network Simulator
API
onion-routing-dummy-encryption-example.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 
3 
4 /*
5 * Copyright (c) 2020 DLTLT
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation;
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 * Author: Niki Hrovatin <niki.hrovatin@famnit.upr.si>
21 */
22 
23 
24 
25 /*
26  * Example of implementation and use of the OnionRouting class
27  *
28  *
29  * The given example can be used to construct onion messages of the following features:
30  * 0- ONION_NO_CONTENT - onion message including only routing information
31  * 1- ONION_ENDCONTENT - onion message including content to be delivered to the last node in the path
32  * 2- ONION_LAYERCONTENT - onion message including a content of fixed length (in bytes) in each layer
33  * 3- ONION_LAYERCONTENT_ENDCONTENT - onion message including a content of fixed length in each layer and
34  * content of arbitrary length to be delivered to the last node in the path
35  *
36  * The listed onion messagess are selected through the cmd argument onionMode. This argument defines the mode of operation of the example code.
37  * (The value preceeding the name should be given to the cmd argument)
38  *
39  *
40  * Network topology
41  *
42  *
43  * n2-------------n3
44  * / \ /
45  * / \(1Mbps,3ms)/
46  * / \ /
47  * (5Mbps,2ms)/ \ /
48  * / \ /
49  * / \ /
50  * / \ /
51  * n0-----------n1 n4----------n5
52  * (5Mbps,2ms) (5Mbps,2ms)
53  *
54  *
55  * - all links are point-to-point links with indicated delay
56  * - onion messagess are sent using the UDP protocol
57  *
58  *
59  * Instructions:
60  * 1) run in terminal: ./waf --run "src/internet-apps/examples/onion-routing-dummy-encryption-example.cc --onionMode=1"
61  * --note~ the argument onionMode defines the mode of operation of the example -- see the upper list
62  *
63  *
64  */
65 
67 
68 
69 #include "ns3/point-to-point-module.h"
70 #include "ns3/internet-module.h"
71 #include "ns3/onion-routing.h"
72 #include "ns3/applications-module.h"
73 
74 
75 #define ONION_NO_CONTENT 0
76 #define ONION_ENDCONTENT 1
77 #define ONION_LAYERCONTENT 2
78 #define ONION_LAYERCONTENT_ENDCONTENT 3
79 
80 
81 
82 using namespace ns3;
83 
84 
85 NS_LOG_COMPONENT_DEFINE ("OnionRoutingDummyEncryptionExample");
86 
87 
88 //Serialize an Ipv4Address
89 uint8_t * IpToBuff (Ipv4Address in)
90 {
91  uint8_t * out = new uint8_t[4];
92  in.Serialize (&out[0]);
93  return out;
94 }
95 
96 //Construct Ipv4 address from the serialized form
97 Ipv4Address ConstructIpv4 (uint8_t * buf)
98 {
99  uint32_t ip = 0;
100 
101  ip += buf[0];
102  ip = ip << 8;
103  ip += buf[1];
104  ip = ip << 8;
105  ip += buf[2];
106  ip = ip << 8;
107  ip += buf[3];
108 
109  return Ipv4Address (ip);
110 }
111 
112 
113 
114 //Serialize a string
115 uint8_t * StringToUchar (std::string in)
116 {
117  uint8_t * out = new uint8_t[in.length ()];
118  memcpy (&out[0], &in[0], in.length ());
119  return out;
120 }
121 
122 //Deserialize a string
123 std::string UcharToString (uint8_t* seq, int len)
124 {
125  std::string strForm (&seq[0], &seq[0] + len);
126  return strForm;
127 }
128 
129 
130 
131 
132 
133 //Application to be installed on nodes
134 class MyApp : public Application
135 {
136 public:
137  MyApp (); //constructor
138  MyApp (uint8_t onionMode,uint16_t layerContentLen); //constructor to setup onionMode and layerContent
139  virtual ~MyApp (); //destructor
140 
141  static TypeId GetTypeId (void);//return the typeid
142 
143  //return the pk
144  uint8_t * GetEncryptionKey ();
145  //return ip address of the node
146  Ipv4Address GetAddress ();
147  //Setting up encryption & address
148  void Setup ();
149  void SetRoute (uint16_t routeLen, uint8_t ** ipRoute, uint8_t ** keys, uint8_t ** layerContent, uint8_t layerContentLen);
150 
151 private:
152  virtual void StartApplication (void);
153  virtual void StopApplication (void);
154 
155  void SendOnion ();
156  void RecvOnion (Ptr<Socket> socket);
157 
158  Ptr<Socket> m_socket;
159  Address m_peer;
160  uint16_t m_port;
161  Ipv4Address m_address;
162  OnionRoutingDummyEncryption m_onionManager;
163  uint8_t m_onionMode;
164  uint16_t m_routeLen;
165  uint8_t ** m_ipRoute;
166  uint8_t ** m_keys;
167  uint8_t ** m_layerContent;
168  uint16_t m_layerContentLen;
169 
170 };
171 
172 MyApp::MyApp ()
173  : m_socket (0),
174  m_peer (),
175  m_port (4242),
176  m_onionManager (32,Ipv4L3Protocol::PROT_NUMBER),
177  m_routeLen (0)
178 {}
179 
180 
181 //setup onion mode and length of data to be encrypted in layers
182 MyApp::MyApp (uint8_t onionMode,uint16_t layerContentLen)
183  : m_socket (0),
184  m_peer (),
185  m_port (4242),
186  m_onionManager (32,Ipv4L3Protocol::PROT_NUMBER),
187  m_onionMode (onionMode),
188  m_routeLen (0),
189  m_layerContentLen (layerContentLen)
190 {}
191 
192 
193 MyApp::~MyApp ()
194 {
195  m_socket = 0;
196 }
197 
198 
199 
200 
201 uint8_t * MyApp::GetEncryptionKey ()
202 {
203  return m_onionManager.GetEncryptionKey ();
204 }
205 
206 Ipv4Address MyApp::GetAddress ()
207 {
208  return m_address;
209 }
210 
211 
212 
213 void MyApp::Setup ()
214 {
215 
216  //setup encryption
217  m_onionManager.GenerateNewKey ();
218 
219 
220  //Get node details
221  Ptr<Node> PtrNode = this->GetNode ();
222  Ptr<Ipv4> ipv4 = PtrNode->GetObject<Ipv4> ();
223  Ipv4InterfaceAddress iaddr = ipv4->GetAddress (1, 0);
224  m_address = iaddr.GetLocal ();
225 
226 }
227 
228 //called only on the node who will send the onion
229 //used to set-up the route and content of the onion message
230 void MyApp::SetRoute (uint16_t routeLen, uint8_t ** ipRoute, uint8_t ** keys, uint8_t ** layerContent, uint8_t layerContentLen)
231 {
232  m_routeLen = routeLen;
233  m_ipRoute = ipRoute;
234  m_keys = keys;
235  m_layerContent = layerContent;
236  m_layerContentLen = layerContentLen;
237 }
238 
239 
240 
241 /* static */
242 TypeId MyApp::GetTypeId (void)
243 {
244  static TypeId tid = TypeId ("MyApp")
245  .SetParent<Application> ()
246  .SetGroupName ("OR-dummy-example")
247  .AddConstructor<MyApp> ()
248  ;
249  return tid;
250 }
251 
252 
253 //Construct and send the onion made using the class Onion Routing
254 void
255 MyApp::SendOnion ()
256 {
257 
258  //set the content of the onion message
259  std::string s ("Some content to send anonymously.");
260  uint8_t * content = StringToUchar (s);
261  uint16_t contentLen = s.length ();
262 
263  int cipherLen = 0;
264  uint8_t * cipher;
265 
266  //Construct the onion based on the selected mode
267  if (m_onionMode == ONION_NO_CONTENT)
268  {
269  cipherLen = m_onionManager.OnionLength (m_routeLen,0,0);
270  cipher = new uint8_t[cipherLen];
271 
272  m_onionManager.BuildOnion (cipher, m_ipRoute, m_keys, m_routeLen);
273  }
274  else if (m_onionMode == ONION_ENDCONTENT)
275  {
276  cipherLen = m_onionManager.OnionLength (m_routeLen,0,contentLen);
277  cipher = new uint8_t[cipherLen];
278 
279  m_onionManager.BuildOnion (cipher, m_ipRoute, m_keys, m_routeLen,content,contentLen);
280  }
281  else if (m_onionMode == ONION_LAYERCONTENT)
282  {
283  cipherLen = m_onionManager.OnionLength (m_routeLen,m_layerContentLen,0);
284  cipher = new uint8_t[cipherLen];
285 
286  m_onionManager.BuildOnion (cipher, m_ipRoute, m_keys, m_layerContent, m_layerContentLen, m_routeLen);
287  }
288  else // the case (m_onionMode == ONION_LAYERCONTENT_ENDCONTENT)
289  {
290  cipherLen = m_onionManager.OnionLength (m_routeLen,m_layerContentLen,contentLen);
291  cipher = new uint8_t[cipherLen];
292 
293  m_onionManager.BuildOnion (cipher, m_ipRoute, m_keys, m_layerContent, m_layerContentLen, m_routeLen,content,contentLen);
294  }
295 
296 
297  //Insert the onion in a packet & send to the first node in the route
298  uint8_t const * buff = cipher;
299  Ptr<Packet> p = Create<Packet> (buff,cipherLen);
300  m_socket->SendTo (p, 0, InetSocketAddress (ConstructIpv4 (m_ipRoute[0]),m_port));
301  NS_LOG_INFO ("Onion construction--Onion sent to: " << ConstructIpv4 (m_ipRoute[0]) << " of size: " << p->GetSize () << " bytes" );
302 
303 }
304 
305 //Performed when the node receives an onion
306 void
307 MyApp::RecvOnion (Ptr<Socket> socket)
308 {
309  Address from;
310  Ptr<Packet> p = socket->RecvFrom (from);
311 
312  //extract onion from the packet
313  uint32_t cipherLen = p->GetSize ();
314 
315  if (cipherLen == 0 )//execute if onion mode -- ONION_NO_CONTENT -- was selected
316  {
317  NS_LOG_INFO ("Onion reveal--Empty onion sent from: " << InetSocketAddress::ConvertFrom (from).GetIpv4 () << " received at: " << m_address );
318  return;
319  }
320 
321  uint8_t cipher[cipherLen];
322  p->CopyData (cipher, cipherLen);
323 
324  //decrypt onion layer
325  orLayer * onionLayer = m_onionManager.PeelOnion (cipher,cipherLen,m_onionManager.GetEncryptionKey (),m_onionManager.GetEncryptionKey ());
326 
327 
328  if (ConstructIpv4 (onionLayer->nextHopIP).Get () == 0) //execute if onion mode -- -- was selected
329  {//Onion totally decrypted
330  NS_LOG_INFO ("Onion reveal--Onion sent from: " << InetSocketAddress::ConvertFrom (from).GetIpv4 () << " received at: " << m_address << " of size: " << p->GetSize () << " bytes, containing the end content:" << UcharToString (onionLayer->innerLayer,onionLayer->innerLayerLen));
331  }
332  else
333  {//Onion routing step
334  if (m_onionMode == ONION_LAYERCONTENT || m_onionMode == ONION_LAYERCONTENT_ENDCONTENT) //execute if onion mode -- ONION_LAYERCONTENT,ONION_LAYERCONTENT_ENDCONTENT -- was selected
335  {
336  uint8_t const * buff = &onionLayer->innerLayer[m_layerContentLen];
337  Ptr<Packet> np = Create<Packet> (buff,onionLayer->innerLayerLen - m_layerContentLen);
338  m_socket->SendTo (np, 0, InetSocketAddress (ConstructIpv4 (onionLayer->nextHopIP),m_port));
339  NS_LOG_INFO ("Onion routing--Onion sent from: " << InetSocketAddress::ConvertFrom (from).GetIpv4 () << " received at: " << m_address << " of size: " << p->GetSize () << " bytes, containing the layer content: " << UcharToString (onionLayer->innerLayer,m_layerContentLen) << ", sent to: " << ConstructIpv4 (onionLayer->nextHopIP));
340 
341  }
342  else //execute if onion mode -- ONION_NO_CONTENT, ONION_ENDCONTENT, -- was selected
343  {
344  uint8_t const * buff = onionLayer->innerLayer;
345  Ptr<Packet> np = Create<Packet> (buff,onionLayer->innerLayerLen);
346  m_socket->SendTo (np, 0, InetSocketAddress (ConstructIpv4 (onionLayer->nextHopIP),m_port));
347  NS_LOG_INFO ("Onion routing--Onion sent from: " << InetSocketAddress::ConvertFrom (from).GetIpv4 () << " received at: " << m_address << " of size: " << p->GetSize () << " bytes, sent to: " << ConstructIpv4 (onionLayer->nextHopIP));
348  }
349  }
350 
351 
352 }
353 
354 
355 void
356 MyApp::StartApplication (void)
357 {
358 
359  //Create socket
360  m_socket = Socket::CreateSocket (this->GetNode (), TypeId::LookupByName ("ns3::UdpSocketFactory"));
361  m_socket->Bind (InetSocketAddress (Ipv4Address::GetAny (), m_port));
362  m_socket->SetRecvCallback (MakeCallback (&MyApp::RecvOnion,this));
363 
364  //Check if the node has a route for the onion
365  if (m_routeLen != 0)
366  {
367  //Schedule an onion routing
368  Simulator::Schedule (Seconds (2), &MyApp::SendOnion, this);
369  }
370 
371 }
372 
373 void
374 MyApp::StopApplication (void)
375 {
376 
377  m_socket->Close ();
378 
379 }
380 
381 
382 
383 
384 
385 
386 
387 
388 int
389 main (int argc, char *argv[])
390 {
391  bool verbose = true;
392  uint8_t onionMode = ONION_ENDCONTENT;
393 
394  CommandLine cmd (__FILE__);
395  cmd.AddValue ("verbose", "Tell application to log if true", verbose);
396  cmd.AddValue ("onionMode", "Select the mode of operation", onionMode);
397 
398  cmd.Parse (argc,argv);
399 
400  if (verbose)
401  {
402  LogComponentEnable ("OnionRoutingDummyEncryptionExample", LOG_LEVEL_INFO);
403  LogComponentEnable ("onionrouting", LOG_LEVEL_INFO);
404 
405  }
406 
407  if ( onionMode > 3)
408  {
409  NS_FATAL_ERROR ("Wrong mode of operation selected, select one in range 0 to 3");
410  }
411 
412  /* ... */
413 
414 
415 
416  //create the topology of six nodes
417  NodeContainer nc;
418  nc.Create (6);
419  NodeContainer n0n1 = NodeContainer(nc.Get(0),nc.Get(1));
420  NodeContainer n1n2 = NodeContainer(nc.Get(1),nc.Get(2));
421  NodeContainer n2n3 = NodeContainer(nc.Get(2),nc.Get(3));
422  NodeContainer n2n4 = NodeContainer(nc.Get(2),nc.Get(4));
423  NodeContainer n3n4 = NodeContainer(nc.Get(3),nc.Get(4));
424  NodeContainer n4n5 = NodeContainer(nc.Get(4),nc.Get(5));
425 
426 
427  //Install internet stack
428  InternetStackHelper stack;
429  stack.Install (nc);
430 
431  //Create Point-to-Point Channels
432  NS_LOG_INFO ("Create channels.");
433  PointToPointHelper p2p;
434  p2p.SetDeviceAttribute ("DataRate",StringValue ("5Mbps"));
435  p2p.SetChannelAttribute("Delay",StringValue("2ms"));
436  NetDeviceContainer d0d1 = p2p.Install (n0n1);
437 
438  NetDeviceContainer d1d2 = p2p.Install (n1n2);
439 
440  NetDeviceContainer d4d5 = p2p.Install (n4n5);
441 
442  p2p.SetDeviceAttribute ("DataRate",StringValue ("1Mbps"));
443  p2p.SetChannelAttribute("Delay",StringValue("3ms"));
444  NetDeviceContainer d2d3 = p2p.Install (n2n3);
445  NetDeviceContainer d3d4 = p2p.Install (n3n4);
446  NetDeviceContainer d2d4 = p2p.Install (n2n4);
447 
448 
449 
450  //setup ip addressses
451  Ipv4AddressHelper address;
452 
453  address.SetBase ("10.1.1.0", "255.255.255.0");
454  Ipv4InterfaceContainer i0i1 = address.Assign (d0d1);
455 
456  address.SetBase ("10.1.2.0", "255.255.255.0");
457  Ipv4InterfaceContainer i1i2 = address.Assign (d1d2);
458 
459  address.SetBase ("10.1.3.0", "255.255.255.0");
460  Ipv4InterfaceContainer i2i3 = address.Assign (d2d3);
461 
462  address.SetBase ("10.1.4.0", "255.255.255.0");
463  Ipv4InterfaceContainer i3i4 = address.Assign (d3d4);
464 
465  address.SetBase ("10.1.5.0", "255.255.255.0");
466  Ipv4InterfaceContainer i2i4 = address.Assign (d2d4);
467 
468  address.SetBase ("10.1.6.0", "255.255.255.0");
469  Ipv4InterfaceContainer i4i5 = address.Assign (d4d5);
470 
471  //set routing
472  Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
473 
474 
475  //define route of the onion
476  uint16_t routeLen = 5;
477  uint8_t * ipRoute[routeLen];
478  uint8_t * keys[routeLen];
479  uint16_t layerContentLen = 27; //hardcoded
480  uint8_t * layerContent[routeLen];
481 
482 
483  //Install apps on nodes
484  ApplicationContainer applications (CreateObject<MyApp> (onionMode,layerContentLen));
485  applications.Add (CreateObject<MyApp> (onionMode,layerContentLen));
486  applications.Add (CreateObject<MyApp> (onionMode,layerContentLen));
487  applications.Add (CreateObject<MyApp> (onionMode,layerContentLen));
488  applications.Add (CreateObject<MyApp> (onionMode,layerContentLen));
489  applications.Add (CreateObject<MyApp> (onionMode,layerContentLen));
490 
491  nc.Get (0)->AddApplication (applications.Get (0));
492  nc.Get (1)->AddApplication (applications.Get (1));
493  nc.Get (2)->AddApplication (applications.Get (2));
494  nc.Get (3)->AddApplication (applications.Get (3));
495  nc.Get (4)->AddApplication (applications.Get (4));
496  nc.Get (5)->AddApplication (applications.Get (5));
497 
498 
499  //setup encryption & address
500  for (uint32_t i = 0; i < applications.GetN (); ++i)
501  {
502  /* code */
503  applications.Get (i)->GetObject<MyApp> ()->Setup ();
504  }
505 
506 
507  //ip addresses of the route
508  ipRoute[0] = IpToBuff (applications.Get (2)->GetObject<MyApp> ()->GetAddress ());
509  ipRoute[1] = IpToBuff (applications.Get (3)->GetObject<MyApp> ()->GetAddress ());
510  ipRoute[2] = IpToBuff (applications.Get (1)->GetObject<MyApp> ()->GetAddress ());
511  ipRoute[3] = IpToBuff (applications.Get (4)->GetObject<MyApp> ()->GetAddress ());
512  ipRoute[4] = IpToBuff (applications.Get (5)->GetObject<MyApp> ()->GetAddress ());
513 
514  //encryption keys of nodes in the route
515  keys[0] = applications.Get (2)->GetObject<MyApp> ()->GetEncryptionKey ();
516  keys[1] = applications.Get (3)->GetObject<MyApp> ()->GetEncryptionKey ();
517  keys[2] = applications.Get (1)->GetObject<MyApp> ()->GetEncryptionKey ();
518  keys[3] = applications.Get (4)->GetObject<MyApp> ()->GetEncryptionKey ();
519  keys[4] = applications.Get (5)->GetObject<MyApp> ()->GetEncryptionKey ()
520  ; //set content of each layer
521  layerContent[0] = StringToUchar ("OnionLayer 4 secret content");
522  layerContent[1] = StringToUchar ("OnionLayer 3 secret content");
523  layerContent[2] = StringToUchar ("OnionLayer 2 secret content");
524  layerContent[3] = StringToUchar ("OnionLayer 1 secret content");
525  layerContent[4] = StringToUchar ("OnionLayer 0 secret content");
526 
527  //setup the route at node 0, the node 0 will send the onion
528  applications.Get (0)->GetObject<MyApp> ()->SetRoute (routeLen,ipRoute,keys,layerContent,layerContentLen);
529 
530 
531  applications.Start (Seconds (1));
532  applications.Stop (Seconds (20));
533 
534 
535  Simulator::Stop (Seconds (20));
536  Simulator::Run ();
537  Simulator::Destroy ();
538  return 0;
539 }
540 
541 
542 
ns3
Definition: sensornode-helper.cc:26
ns3::orLayer::nextHopIP
uint8_t * nextHopIP
ip address given in the serialized form
Definition: onion-routing.h:23
ns3::orLayer
structure holding details resulting from layer decryption of an onion message
Definition: onion-routing.h:22
ns3::orLayer::innerLayer
uint8_t * innerLayer
inner content of the onion message without the next hop address
Definition: onion-routing.h:24
ns3::orLayer::innerLayerLen
uint16_t innerLayerLen
length of the inner content of the onion message
Definition: onion-routing.h:25
ns3::OnionRoutingDummyEncryption
class that implements the
Definition: onion-routing.h:339