Any good network simulators

Started by
2 comments, last by Drew_Benton 13 years, 1 month ago
I need something to simulate lag/packet loss/dropped connections for windows.
Preferably a software that hooks onto specific apps.
I tried netlimiter but that seems to only limit bandwidth and nothing else.

Anyone know any such software?
Advertisement

I need something to simulate lag/packet loss/dropped connections for windows.


Try running your Windows instance virtualized under KVM or VirtualBox, and use a Linux-based simulator?
I imagine you can use something like "detours" or a simple replacement of ws2_32 to hook into the applications at the API level, too, but I know of nothing that comes pre-rolled.
enum Bool { True, False, FileNotFound };
Hmm well I never used linux in my life except for backtrack 4 and my engine wouldnt run in something like virtual box.
I cant believe that something as simple as a simulator is so hard to do :(

I cant believe that something as simple as a simulator is so hard to do


It's not that hard actually.

All you have to do is write your own proxy that implements a man-in-the-middle attack to route traffic through. That gives you flexibility to:
- delay packets as needed
- drop connections
- modify/corrupt/inject data

The only "hooking" you need to do will be generic detours to make the application connect to your proxy rather than the remote host. That is assuming you cannot change it via a hosts edit or an application specific option.

If you are working with your own application, then you simply implement your protocol so you can process packets from the data stream then relay them to the remote host. If you are working with 3rd party applications, then you will need to know their protocol first to be able to work with their packets.

If that is not possible, then you will only be able to simulate dropped connections and delay the entire network stream without being able to process individual packets. As long as the application you are working with does not implement specific anti-man-in-the-middle attack logic, such as the things mentioned in the "defenses against the attack" section on Wikipedia, or does not employ anti-tamping mechanism like GameGuard, XTrap, Themida packing, etc... this method works very nicely.

Another potential pitfall is if you are working with a application (such as a game) that performs a connection hand off and you don't know the packet protocol, then you will have to do some messy hacks to be able to continue working with the traffic stream at each hand off. It's certainly possible and works, but it is nowhere as elegant as having full control over the protocol.

Once you have your basic proxy done, then you can just add a GUI (or console if you rather work that way) to allow you to do the stuff you need to simulate the network. It's all a matter of logic from there. For example, adding latency is as simple as buffering all packets to a queue rather than dispatching immediately to the other side then checking a timestamp to know when to send it. Connection dropping can be as simple as forcefully closing the socket, but you will not be able to simulate certain types of connection dropping unless you used other tools. I.e., to simulate a connection where the host simply has a power loss, you pretty much need to simulate that yourself on a different machine. That is why running a ritualized instance, such as VirtualBox is great, as hplus mentioned. Likewise for application crashes or network failures.

It might seem like a lot of work at first glance, but these are tools you should already have at your disposal when you are working on a network related project. Existing tools are certainly useful as well, but you can really get the most out of custom tools that cater to your needs exactly. Basically it's a large one time up front investment that pays for itself over time as you develop more and more stuff that you can reuse the tools on. I've had my own generic tools in the past that proved to be quite useful in this regards. Don't expect to be able to find the perfect solution right off the bat. I've played with different designs for this stuff for many years and am still trying new approaches and methods to find the perfect solution for my needs. Getting something that "just works" is simple enough though and the most practical approach to take in your situation.

That should get you pointed in the right way, I hope. Just code a simple traffic relay proxy in whatever language you are using first. Once that is done, you can add your protocol specific logic to break the data stream into packets. Finally, you can add your custom logic to do the tasks you want. You have it pretty easy if all you are working with is your own protocols. You do have to be careful of some 3rd party TCP protocols since they might not be implemented correctly. TCP has been around a very long time, but I still come across games (f2p mmos) that incorrectly treat TCP as a packet based protocol and it is very annoying to work with since everything breaks when you do not handle the stream the same way the client does (Nagle algo, send/recv buffer sizes, etc..). Hopefully your own protocol does not make those mistakes. :)

If you need any more ideas on architectures or whatever for such a program feel free to ask. I've been working with this stuff for the past 4 years now trying out different methods, languages, libraries, etc.. to try and come up with the 'ultimate' tool so I've learned a lot along the way. Right now, my focus has been C# (.Net 4.0) + IronPython + Construct and I am extremely pleased with results so far in my early progressions with it. While I can't recommend such experimental ideas for when you have real work to get done, if you are using C++ I'd strongly advise you to checkout boost::asio as your networking core.

The design model they use allows you to do a lot of useful things in the least amount of lines of code. Once you get used to the concepts and the large namespace and write your own wrapper (I talked about mine here) production is greatly increased since you are spending less time worrying about the things boost::asio does for you that you otherwise would if you rolled your own using native Winsock. I spent many years trying to do it myself and after wasting so much time and ending up with such limited code, I finally heeded the advice of people who knew a lot more than me and learned an existing library that took care of everything. I don't regret it one bit and make heavy use of it for my C++ stuff. For example, using my network wrapper my own basic traffic relay proxy code would look like this:
[spoiler]
#include "network.h"
#include <conio.h>

class MyConnection : public Connection
{
private:
boost::weak_ptr<MyConnection> m_relay;
int m_type;

private:
void OnAccept( const std::string & host, uint16_t port )
{
}

void OnConnect( const std::string & host, uint16_t port )
{
boost::shared_ptr<MyConnection> relay = m_relay.lock();
if(relay)
{
Recv(); // Trigger our receive logic
relay->Recv(); // Trigger our relay receive logic
}
else
{
Disconnect();
return;
}
}

void OnSend( const std::vector< uint8_t > & buffer )
{
}

void OnRecv( std::vector< uint8_t > & buffer )
{
boost::shared_ptr<MyConnection> relay = m_relay.lock();
if(relay)
{
relay->Send(buffer); // Pass to relay object.
}
else
{
Disconnect();
return;
}
Recv(); // Start the next receive
}

void OnTimer( const boost::posix_time::time_duration & delta )
{
}

void OnError( const boost::system::error_code & error )
{
boost::shared_ptr<MyConnection> relay = m_relay.lock();
if(relay)
{
relay->Disconnect(); // Don't let one end exist without the other
}
}

public:
MyConnection( boost::shared_ptr< Hive > hive )
: Connection( hive ), m_type(0)
{
}

~MyConnection()
{
}

void SetRelay(boost::shared_ptr<MyConnection> relay, int type)
{
m_relay = relay;
m_type = type;
}
};

class MyAcceptor : public Acceptor
{
private:

private:
bool OnAccept( boost::shared_ptr< Connection > connection, const std::string & host, uint16_t port )
{
boost::shared_ptr< MyConnection > current_connection = boost::dynamic_pointer_cast< MyConnection >( connection );
boost::shared_ptr< MyConnection > relay_connection( new MyConnection( GetHive() ) );

current_connection->SetRelay(relay_connection, 0);
relay_connection->SetRelay(current_connection, 1);

relay_connection->Connect("<host>", 0; // todo: fill in your address

current_connection->SetTimerInterval(100);
relay_connection->SetTimerInterval(100);

return true;
}

void OnTimer( const boost::posix_time::time_duration & delta )
{
}

void OnError( const boost::system::error_code & error )
{
}

public:
MyAcceptor( boost::shared_ptr< Hive > hive )
: Acceptor( hive )
{
}

~MyAcceptor()
{
}
};

int main( int argc, char * argv[] )
{
boost::shared_ptr< Hive > hive( new Hive() );

boost::shared_ptr< MyAcceptor > acceptor( new MyAcceptor( hive ) );
acceptor->Listen( "127.0.0.1", 7777 );

boost::shared_ptr< MyConnection > connection( new MyConnection( hive ) );
acceptor->Accept( connection );

while( !_kbhit() )
{
hive->Poll();
Sleep( 1 );
}

hive->Stop();

return 0;
}
[/spoiler]
And it's ready to have the protocol processing object dropped in then the custom logic added. So all my work is focused on everything but the underlying network code I'd otherwise have to write if I didn't have my own wrapper already written and wasn't using an existing network library. The advantage of using boost vs rolling my own in this case would be I can easily add multithread support, it's cross platform, and it's a proven library that can be used for larger scale projects (although I can't recommend using my wrapper since there are a few bugs and some specific tradeoffs with the style I used, mostly related to overhead and lackof memory management).

As part of another recent enlightenment I had though reading these forums though, I'm transitioning my tool development to higher level languages because the solutions that I wanted to express through C++ were simply taking too much time, effort, and ended up so mediocre that I just got tired of it. I'll stop rambling, but keep in mind to find the best tools for the job rather than just force a solution through what's most known.You didn't mention what language(s) you are using or which network protocols, but TCP and C++ are what I've had the most experience with so far, so that's what I choose to talk about.;)

Good luck!

This topic is closed to new replies.

Advertisement