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 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
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->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<
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.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
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 ();
…………………………….
………………………….
}
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