Skip to content

Simulating Low-Rate TCP DoS Attacks under ns-3


Low-Rate TCP DoS attack is the second class of attacks that was explained by Kuzmanovic and Knightly’s in their paper, “Low-Rate TCP-Targeted Denial of Service Attacks”. In that paper, the authors demonstrate an attack, by sending a precisely timed square-wave pattern of packet bursts and hence the attacker can interfere with a TCP flow’s retransmissions on a bottleneck link.

As they state, “At times of severe congestion in which multiple losses occur, TCP operates on longer timescales of Retransmission Timeout (RTO). Using this knowledge, an attacker can send periodic on-off square-wave shrew attacks that consist of short, maliciously-chosen-duration bursts that repeat with a fixed, maliciously chosen, slow-timescale frequency”.

They showed that precisely-timed attack traffic in the form of a square wave whose period is set with respect to the target flow’s minRTO value, the attacker can affect the throughput of TCP Reno flow that shares the same bottleneck link. 

The following diagram shows the waveform of the traffic generated by the attacker.

The following shows the NetAnim Scenario of  Low-Rate TCP DoS  Attacks that was simulated under ns-3

Important Sections of the Simulation Script

The parameters of Traffic

 
#define TCP_SINK_PORT 9000
#define UDP_SINK_PORT 9001 // Experimentation parameters
#define BULK_SEND_MAX_BYTES 2097152
#define MAX_SIMULATION_TIME 50.0
#define ATTACKER_START 0.0
#define ATTACKER_RATE (std::string)”12000kb/s”
#define ON_TIME (std::string)”0.25″
#define BURST_PERIOD 1
#define OFF_TIME (std::string)”0.75″
//std::to_string(BURST_PERIOD – stof(ON_TIME))
#define SENDER_START 0.75 // Must be equal to OFF_TIME

For Tracing TCP Dynamics

static void
CwndTracer (uint32_t oldval, uint32_t newval)
{
if (firstCwnd)
{
*cWndStream->GetStream () << “0.0 ” << oldval << std::endl;
firstCwnd = false;
}
*cWndStream->GetStream () << Simulator::Now ().GetSeconds () << ” ” << newval << std::endl;
cWndValue = newval; if (!firstSshThr)
{
*ssThreshStream->GetStream () << Simulator::Now ().GetSeconds () << ” ” << ssThreshValue << std::endl;
}
} static void
SsThreshTracer (uint32_t oldval, uint32_t newval)
{
if (firstSshThr)
{
*ssThreshStream->GetStream () << “0.0 ” << oldval << std::endl;
firstSshThr = false;
}
*ssThreshStream->GetStream () << Simulator::Now ().GetSeconds () << ” ” << newval << std::endl;
ssThreshValue = newval; if (!firstCwnd)
{
*cWndStream->GetStream () << Simulator::Now ().GetSeconds () << ” ” << cWndValue << std::endl;
}
} static void
RttTracer (Time oldval, Time newval)
{
if (firstRtt)
{
*rttStream->GetStream () << “0.0 ” << oldval.GetSeconds () << std::endl;
firstRtt = false;
}
*rttStream->GetStream () << Simulator::Now ().GetSeconds () << ” ” << newval.GetSeconds () << std::endl;
} static void
RtoTracer (Time oldval, Time newval)
{
if (firstRto)
{
*rtoStream->GetStream () << “0.0 ” << oldval.GetSeconds () << std::endl;
firstRto = false;
}
*rtoStream->GetStream () << Simulator::Now ().GetSeconds () << ” ” << newval.GetSeconds () << std::endl;
}
static void
TraceCwnd (std::string cwnd_tr_file_name)
{
AsciiTraceHelper ascii;
cWndStream = ascii.CreateFileStream (cwnd_tr_file_name.c_str ());
Config::ConnectWithoutContext (“/NodeList/0/$ns3::TcpL4Protocol/SocketList/0/CongestionWindow”, MakeCallback (&CwndTracer));
} static void
TraceSsThresh (std::string ssthresh_tr_file_name)
{
AsciiTraceHelper ascii;
ssThreshStream = ascii.CreateFileStream (ssthresh_tr_file_name.c_str ());
Config::ConnectWithoutContext (“/NodeList/0/$ns3::TcpL4Protocol/SocketList/0/SlowStartThreshold”, MakeCallback (&SsThreshTracer));
} static void
TraceRtt (std::string rtt_tr_file_name)
{
AsciiTraceHelper ascii;
rttStream = ascii.CreateFileStream (rtt_tr_file_name.c_str ());
Config::ConnectWithoutContext (“/NodeList/0/$ns3::TcpL4Protocol/SocketList/0/RTT”, MakeCallback (&RttTracer));
} static void
TraceRto (std::string rto_tr_file_name)
{
AsciiTraceHelper ascii;
rtoStream = ascii.CreateFileStream (rto_tr_file_name.c_str ());
Config::ConnectWithoutContext (“/NodeList/0/$ns3::TcpL4Protocol/SocketList/0/RTO”, MakeCallback (&RtoTracer));
}

The Outine of the Main Function 

int main(int argc, char *argv[])
{
………………..

……………………….


NodeContainer nodes;
nodes.Create(5);

MobilityHelper mobility;

mobility.SetPositionAllocator (“ns3::GridPositionAllocator”,
“MinX”, DoubleValue (0.0), “MinY”, DoubleValue (0.0),”DeltaX”, DoubleValue (10.0), “DeltaY”, DoubleValue (10.0),
“GridWidth”, UintegerValue (10), “LayoutType”, StringValue (“RowFirst”));

mobility.SetMobilityModel (“ns3::ConstantPositionMobilityModel”);
mobility.Install (nodes);

bool SimulateErrorModel=false;
double error_p = 0.01;
RateErrorModel error_model;

if (SimulateErrorModel) {
// Configure the error model
// Here we use RateErrorModel with packet error rate
Ptr uv = CreateObject ();
uv->SetStream (50);

error_model.SetRandomVariable (uv);
error_model.SetUnit (RateErrorModel::ERROR_UNIT_PACKET);
error_model.SetRate (error_p);
}


Setting  Flow :


std::string TcpProtocolName = “TcpWestwoodPlus”;

/
if (TcpProtocolName.compare (“TcpNewReno”) == 0)
{
Config::SetDefault (“ns3::TcpL4Protocol::SocketType”, TypeIdValue (TcpNewReno::GetTypeId ()));
}
else if 

…………………………………………………..

…………………………………………………
}
else
{
std::cout<std::cout<<“\tInvalid TCP version\n:”;
exit (1);
}

// Define the Point-to-Point links (helpers) and their paramters
PointToPointHelper pp1, pp2;
pp1.SetDeviceAttribute(“DataRate”, StringValue(“100Mbps”));
pp1.SetChannelAttribute(“Delay”, StringValue(“1ms”));

// Add a DropTailQueue to the bottleneck link
pp2.SetQueue(“ns3::DropTailQueue”, “MaxPackets”, UintegerValue(1));
pp2.SetDeviceAttribute(“DataRate”, StringValue(“1.5Mbps”));
pp2.SetChannelAttribute(“Delay”, StringValue(“20ms”));

if (SimulateErrorModel) {
pp2.SetDeviceAttribute (“ReceiveErrorModel”, PointerValue (&error_model));
}
// Install the Point-to-Point links between nodes
NetDeviceContainer d02, d12, d23, d34;
d02 = pp1.Install(nodes.Get(0), nodes.Get(2));
d12 = pp1.Install(nodes.Get(1), nodes.Get(2));
d23 = pp2.Install(nodes.Get(2), nodes.Get(3));
d34 = pp1.Install(nodes.Get(3), nodes.Get(4));


InternetStackHelper stack;
stack.Install(nodes);


Ipv4AddressHelper a02, a12, a23, a34;
a02.SetBase(“10.1.1.0”, “255.255.255.0”);
a12.SetBase(“10.1.2.0”, “255.255.255.0”);
a23.SetBase(“10.1.3.0”, “255.255.255.0”);
a34.SetBase(“10.1.4.0”, “255.255.255.0”);


Ipv4InterfaceContainer i02, i12, i23, i34;
i02 = a02.Assign(d02);
i12 = a12.Assign(d12);
i23 = a23.Assign(d23);
i34 = a34.Assign(d34);

bool DoSAttack=true;
bool TcpTraffic=true;

if (DoSAttack) {
// UDP On-Off Application – Application used by attacker (eve) to create the low-rate bursts.
OnOffHelper onoff(“ns3::UdpSocketFactory”,
Address(InetSocketAddress(i34.GetAddress(1), UDP_SINK_PORT)));
onoff.SetConstantRate(DataRate(ATTACKER_RATE));
onoff.SetAttribute(“OnTime”, StringValue(“ns3::ConstantRandomVariable[Constant=” + ON_TIME + “]”));
onoff.SetAttribute(“OffTime”, StringValue(“ns3::ConstantRandomVariable[Constant=” + OFF_TIME + “]”));
ApplicationContainer onOffApp = onoff.Install(nodes.Get(1));
onOffApp.Start(Seconds(ATTACKER_START));
onOffApp.Stop(Seconds(MAX_SIMULATION_TIME));
}

if (TcpTraffic) {
// TCP Bulk Send Application – Application used by the legit node (alice) to send data to a receiver.
BulkSendHelper bulkSend(“ns3::TcpSocketFactory”,
InetSocketAddress(i34.GetAddress(1), TCP_SINK_PORT));
bulkSend.SetAttribute(“MaxBytes”, UintegerValue(BULK_SEND_MAX_BYTES));
ApplicationContainer bulkSendApp = bulkSend.Install(nodes.Get(0));
bulkSendApp.Start(Seconds(SENDER_START));
bulkSendApp.Stop(Seconds(MAX_SIMULATION_TIME));
}

if (DoSAttack) {
// UDP sink on the receiver (bob).
PacketSinkHelper UDPsink(“ns3::UdpSocketFactory”,
Address(InetSocketAddress(Ipv4Address::GetAny(), UDP_SINK_PORT)));
ApplicationContainer UDPSinkApp = UDPsink.Install(nodes.Get(4));
UDPSinkApp.Start(Seconds(0.0));
UDPSinkApp.Stop(Seconds(MAX_SIMULATION_TIME));
}


if (TcpTraffic) {
// TCP sink on the receiver (bob).
PacketSinkHelper TCPsink(“ns3::TcpSocketFactory”,
InetSocketAddress(Ipv4Address::GetAny(), TCP_SINK_PORT));
ApplicationContainer TCPSinkApp = TCPsink.Install(nodes.Get(4));
TCPSinkApp.Start(Seconds(0.0));
TCPSinkApp.Stop(Seconds(MAX_SIMULATION_TIME));
}

Ipv4GlobalRoutingHelper::PopulateRoutingTables();


std::string prefix_file_name = “TcpComparison”;
bool tracing = true;

// Set up tracing if enabled
if (tracing)
{
std::ofstream ascii;
Ptr ascii_wrap;
ascii.open ((prefix_file_name + “-ascii”).c_str ());
ascii_wrap = new OutputStreamWrapper ((prefix_file_name + “-ascii”).c_str (),
std::ios::out);
stack.EnableAsciiIpv4All (ascii_wrap);

Simulator::Schedule (Seconds (SENDER_START+5), &TraceCwnd, prefix_file_name + “-cwnd.data”);
Simulator::Schedule (Seconds (SENDER_START+5), &TraceSsThresh, prefix_file_name + “-ssth.data”);
Simulator::Schedule (Seconds (SENDER_START+5), &TraceRtt, prefix_file_name + “-rtt.data”);
Simulator::Schedule (Seconds (SENDER_START+5), &TraceRto, prefix_file_name + “-rto.data”);
}


AnimationInterface anim (“TcpLowRateDosAttackSimulation_NetAnimationOutput.xml”);

…………………………….

………………………….

AsciiTraceHelper eventTraces;
pp1.EnableAsciiAll(eventTraces.CreateFileStream(“TcpLowRateDosAttackSimulation_EventTraceOutput.tr”));

…………………………….

………………………….



Ptr flowMonitor;
FlowMonitorHelper flowHelper;
flowMonitor = flowHelper.InstallAll();
Simulator::Stop (Seconds (MAX_SIMULATION_TIME));
Simulator::Run();
Simulator::Destroy();

flowMonitor->SerializeToXmlFile(“TcpLowRateDosAttackSimulation_FlowMonitorOutput.xml”, true, true);

// Print per flow statistics
flowMonitor->CheckForLostPackets ();

…………………………….

………………………….

}

In the main() section of the code, the nodes are created and loaded with internet stack and the connection is established between the source and destination nodes. The call back function is scheduled so that cwnd and rtt dynamics will be logged periodically.
 

NetAnim Output

The following NetAnim Instance shows the Low-Rate TCP DoS attack in action

 

Event Traces

The Following  Output shows the Event Traces that were displayed during Running the ns-3 simulation:

 

The Flow Statistics

The Following is the Flow Statistics File Created by FlowMonitor

 

The Terminal Output


The Following Terminal Output shows the packet Statistics Without the Presence of DoS Attack :

The Following Terminal Output shows the packet Statistics With the Presence of Low-Rate TCP DoS attack :

 

One may do some elementary analysis using the following approach:

Trace Analysis of TCP Flows Under ns-3 MANET/ FANET/ VANET/ WSN Scenario

 

References 

  1. https://dl.acm.org/doi/10.1145/863955.863966

 

WhatsApp Discuss Through WhatsApp