What could be blocking spoofed UDP packets on Windows computer? - javascript

I tried to create a simple IP address spoofing program. The goal is to convince computer game on local network to connect to an internet server. The game only discovers servers via UDP broadcast and won't accept server IP.
So instead I want to trick the game into thinking that it received answer info from the internet server by creating a fake UDP packet.
I successfully used raw-socket to generate IPV4 packet with UDP payload. As long as I set the correct IP it gets sent.
However, If I put fake IP in the packet, it won't get out of the machine. I can't see it in Wireshark on my machine. I also noticed that something corrects IPV4 checksums on my packet. I always send checksum 0xFFFF, but Wireshark sees this:
How I send it using raw-socket:
const raw = require("raw-socket");
const UDPPacket = require("../generic/UDPPacket");
const IPV4Packet = require("../generic/IPV4Packet");
var socket = raw.createSocket({ protocol: raw.Protocol.UDP });
socket.on("message", function (buffer, source) {
console.log("received " + buffer.length + " bytes from " + source);
});
// UDPPacket and IPV4 packet are classes that I wrote in order to
// generate the UDP and IPV4 byte data
const packet = new UDPPacket();
packet.srcPort = 27888;
packet.dstPort = 1234;
packet.data = responseBuffer;
const buf = packet.fullBuffer;
const ipv4packet = new IPV4Packet();
ipv4packet.payloadBuffer = buf;
// I send the message form several IPs, but only mine works
const iprand = "192.168.110.";
let ipincrement = 75 * 2;
// my actual IP right now
ipv4packet.srcAddr = "192.168.110.79";
ipv4packet.dstAddr = "192.168.110.1";
setInterval(() => {
// Try to send it from another IP
ipv4packet.srcAddr = iprand + Math.round((++ipincrement)/2);
const ipv4buf = ipv4packet.fullBuffer;
socket.send(ipv4buf, 0, ipv4buf.length, ipv4packet.dstAddr, function (error, bytes) {
// I'm not sure what does this exactly do,
// I found it on the internet ¯\_(ツ)_/¯
// But without it, I cannot send the IPV4 headers
socket.setOption(
raw.SocketLevel.IPPROTO_IP,
raw.SocketOption.IP_HDRINCL,
new Buffer([0x01, 0x00, 0x00, 0x00]),
4
);
},
function (error, bytes) {
// always prints that bytes were sent
if (error)
console.log(error.toString());
else
console.log(bytes, " bytes sent!");
}
);
}, 700)
Who is blocking and changing my packets? I tried disabling firewall, didn't help.
Note that the messages are getting lost EVEN IF THE TARGET IS THE LOCAL MACHINE.

See https://msdn.microsoft.com/en-us/library/windows/desktop/ms740548(v=vs.85).aspx:
On Windows 7, Windows Vista, Windows XP with Service Pack 2 (SP2), and Windows XP with Service Pack 3 (SP3), the ability to send traffic over raw sockets has been restricted in several ways:
UDP datagrams with an invalid source address cannot be sent over raw sockets. The IP source address for any outgoing UDP datagram must exist on a network interface or the datagram is dropped. This change was made to limit the ability of malicious code to create distributed denial-of-service attacks and limits the ability to send spoofed packets (TCP/IP packets with a forged source IP address).

Related

C# WebSocket - No response from client during handshake

I'm attempting to write a C# WebSocket server for an application that interacts upon browser input.
This is the code:
class Program {
static void Main(string[] args) {
var listener = new TcpListener(IPAddress.Parse("127.0.0.1"), 42001);
listener.Start();
using(var client = listener.AcceptTcpClient())
using(var stream = client.GetStream())
using(var reader = new StreamReader(stream))
using(var writer = new StreamWriter(stream)) {
while (!reader.EndOfStream) {
String line = reader.ReadLine();
if (new Regex("^GET").IsMatch(line)) {
line = reader.ReadLine();
if (new Regex("^Sec-WebSocket-Key: ").IsMatch(line)) {
String key = new Regex("(^Sec-WebSocket-Key\\: |\\r\\n)").Replace(line, "");
key = Convert.ToBase64String(SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11")));
writer.WriteLine("HTTP/1.1 101 Switching Protocols");
writer.WriteLine("Upgrade: websocket");
writer.WriteLine("Connection: Upgrade");
writer.WriteLine("Sec-WebSocket-Accept: " + key);
writer.WriteLine("Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits");
writer.WriteLine("WebSocket-Origin: http://127.0.0.1");
writer.WriteLine("WebSocket-Location: ws://localhost:42001/websocket");
writer.WriteLine("");
}
}
}
}
listener.Stop();
}
}
... and:
var ws = new WebSocket('ws://localhost:42001/websocket');
ws.onopen = function() {
console.log('connected');
};
ws.onmessage = function(e) {
console.log(e.data);
};
ws.onerror = function(e) {
console.log(e);
};
ws.onclose = function() {
console.log("closed");
};
On execution, the TPCListener successfully accepts the TCPClient and reads the incoming HTTP request. It parses the Key, generates the correct Accept token, but the JS - window native - WebSocket seems to have gone flat out bonkers: it does not answer no matter what it receives.
I would expect it throwing an error upon sending a HTTP/1.1 400 Bad Request, but nothing at all happens. It just goes mute.
Checking out Chrome Dev Tools' Networking tab, I do only see the websocket outgoing GET request, but no incoming packets - is that supposed to happen?
If I forcefully close the application, WebSocket throws this exception:
WebSocket connection to 'ws://localhost:42001/websocket' failed: Error during WebSocket handshake: net::ERR_CONNECTION_RESET.
What am I missing here? Thank you all in advance.
Also, I'm not using Net.WebSockets because it is available since .NET 4.5, and my application targets systems from Windows 7 to the current build of Windows 10.
well... how far does your C# code get? My first bet would be on buffering - you don't flush the writer or stream, so I would expect them to be holding onto data while stuck in the top of the while loop, but frankly it shouldn't be a while loop in the first place - you only get one handshake per socket, not many. You could try adding flushes after the blank line, and you should make sure the Socket itself has buffering disabled (NoDelay = true;) - but: fundamentally this isn't a good way to write a web-socket server. Apart from anything else, the data will cease to be text if the handshake succeeds, so having a TextReader is a very bad thing. Frankly, you should be dealing with raw Socket / byte[] data here, IMO (having implemented this very thing several times).

Redirect website to unknown internal address

A little background of what I'm doing. I have a home-brew smart thermostat that is connected to my wifi. The device hosts a website that is used to control everything. My main gripe is how unreliable it is to access the device via hostname (especially in android which will be the main controller). I'm trying to find out a way of reliably accessing the device without knowing what the IP address is.
There's two options I'm thinking of, but would like some thoughts on if there are better ways of doing it, or other possible downfalls for my ideas here.
External Website
After wifi configuration, device turns on and sends its internal IP to an external server
External server gets request and logs external IP and associated internal IP
User goes to external website: my.thermostat.com
Website looks up external IP from request, determines internal IP
Website redirects page to internal IP
Therefore, going to my.thermostat.com will redirect to the internal IP.
Downsides:
Requires internet access
Multiple devices with the same external ip?
Android/iOS App
Launch app
App scans current subnet for device
Sends request to each IP: http://x.x.x.x/isThermostat.html
When an expected response is received, launch browser to that IP
Downsides:
Requires app to access control panel
What to do if you want to access via computer? Rely on hostname?
The app route seems like it would be the least complicated, but I like the idea of being able to access the thermostat with any device, so it would still be a little tricky on computers.
Any thoughts would be greatly appreciated!
EDIT
Giving some more info on the hardware itself, it's an arduino yun that will either be connected either via ethernet or wifi. I'd like to stay away from static configurations or setting static DHCP leases. I imagine making a couple of these to give to friends and whatnot, so the least amount of user setup the better.
Can you give an static internal IP ?
Normally in your home router you have a option to give static IP to a given MAC address, or you the definition of the device to setup the static IP.
I think both of your solutions are two complex for something simple.
You should consider a static IP for the device, disabling DHCP on the device and configuring a static IP in the router that refers to the MAC hardware address of the device. This should avoid problems with changing a hostname. Essentially it will allow for you to refer the address within the LAN with a consistent IP.
You haven't mentioned exactly what device it is, so I can't suggest a clear configuration setup, but you should be able to Google for answers. What you do next depends on what you need to achieve.
If you need to access the device from the WAN (Internet) then you need a dynamic DNS service like https://duckdns.org/why.jsp
A DDNS is a hosted service that forwards requests to a subdomain, like: thermostat.duckdns.org to your WAN IP (your router/modem). You install a helper application inside your network that lets the DDNS know every 5 minutes what your WAN IP is, therefore keeping it pointing at you.
From there if you visit: thermostat.duckdns.org it will forward you to your WAN IP, from which point your router then decides what to do with the request. You'll want to setup your router to port forward (port 80 for a web server such as apache) that points to your internal static IP of your thermostat device. Your device then serves the website.
This method allows you to run a web server on an computer or device within a LAN that is accessible from WAN (Internet).
So I ended up going with the android app that scans the local subnet for the device. I have an html file on the server called knockknock.html that simply has the text "HELLO". For anyone interested, here's a first rendition of the code I'm using:
/*
* Get the IP and subnet info and start scanning the local subnet
*/
void findServer() {
WifiManager wifi = (WifiManager) this.getSystemService(Context.WIFI_SERVICE);
DhcpInfo dhcp = wifi.getDhcpInfo();
if (dhcp == null) {
Log.d(TAG, "No DHCPInfo on WiFi side.");
}
//Get the string verison of the IP/subnet from the int given by WifiManager
final String ip = intToIp(dhcp.ipAddress);
final String mask = intToIp(dhcp.netmask);
//Start the scanner on a separate thread from the UI
Thread thread = new Thread() {
#Override
public void run() {
serverScanner(ip, mask);
}
};
thread.start();
}
/*
* Convert an integer to a human readable format
*/
String intToIp(int i) {
return ( i & 0xFF) + "." +
((i >> 8 ) & 0xFF) + "." +
((i >> 16 ) & 0xFF) + "." +
((i >> 24 ) & 0xFF ) ;
}
/*
* Scan the given subnet for the server
*/
void serverScanner(String ip, String netmask) {
//Get the first part of the IP
//TODO: Add support for various subnet masks
String iIPv4 = ip.substring(0, ip.lastIndexOf("."));
iIPv4 += ".";
Log.v(TAG, "Current IP Structure: " + iIPv4);
// Loop to scan each address on the local subnet
for (int i = 1; i < 255; i++) {
//Check to see if the server exists
if (checkServer(iIPv4 + i)) {
//It does exist, so let's set the variable and preferences
mServerIP = iIPv4 + i;
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
SharedPreferences.Editor editor = settings.edit();
editor.putString("LastServerIP", mServerIP);
editor.commit();
return; //And we're done here
}
}
}
/*
* Send a request to the server and see if it's alive and what we're looking for
*/
boolean checkServer(String ip) {
BufferedReader inputStream = null;
try {
HttpGet httpget = new HttpGet("http://" + ip + "/knockknock.html");
HttpParams httpParameters = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParameters, 100);
HttpConnectionParams.setSoTimeout(httpParameters, 100);
HttpClient httpclient = new DefaultHttpClient(httpParameters);
HttpResponse response;
response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream instream = entity.getContent();
String result = convertStreamToString(instream);
instream.close();
if (result.equals("HELLO\n")) {
return true;
}
}
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
//No response or not the response we're looking for, so return false
return false;
}

Why can not I open a UDP connection on the client side (in browser)?

I know that there WebSockets. I looked at it from itself is an example of language dart.
void initWebSocket([int retrySeconds = 2]) {
var reconnectScheduled = false;
outputMsg("Connecting to websocket");
ws = new WebSocket('ws://echo.websocket.org');
void scheduleReconnect() {
if (!reconnectScheduled) {
new Timer(new Duration(milliseconds: 1000 * retrySeconds), () => initWebSocket(retrySeconds * 2));
}
reconnectScheduled = true;
}
ws.onOpen.listen((e) {
outputMsg('Connected');
ws.send('Hello from Dart!');
});...
That is nothing but the creation of new connections and work with it already.
That is a separate thread (in fact, in which runs javaScript) connection is established and so on.
Why then dart and JavaScript I can not in the same thread to open a simple UDP connection and work with him?
P.s.UDP is more preferred for online-browser-realtime-games.
The browsers don't support it due to security constraints.
You should take a look at WebRTC
see also
How to send a UDP Packet with Web RTC - Javascript?
Can I use WebRTC to open a UDP connection?

Poor network performance with Websockets running on apple device

I am working on an HTML/Javascript running on mobile devices that is communicating with a Qt/C++ application running on a PC. Both the mobile device and the PC are on a local network. The communication between the HTML page (client) and the C++ app (server) is done using Websockets.
The HTML page is a remote control for the C++ application, so it is needed to have a low latency connection between the mobile device and the PC.
When using any non-Apple device as a client, data is sent to a rate between 60 to 120 frames/sec, which is totally acceptable. When using an Apple device, this rate falls to 3-4 frames/sec.
I also checked ping times (Websocket implementation, not a ping command from command line). They are acceptable (1-5 ms) for Apple devices as long as the device is not transmitting data. Whenever it transmits data, this ping time raises to 200ms.
Looking from the Javascript side, the Apple devices always send data at a consistent rate of 60 frames/sec, as any other devices do. However, on the server side, only 3 to 4 of these 60 frames are received when the client is an Apple device.
Does anyone have any idea on what can be happening?
Here is my Javascript code :
<script language="javascript" type="text/javascript">
var wsUri = document.URL.replace("http", "ws");
var output;
var websocket;
function init()
{
output = document.getElementById("output");
wsConnect();
}
function wsConnect()
{
console.log("Trying connection to " + wsUri);
try
{
output = document.getElementById("output");
websocket = new WebSocket(wsUri);
websocket.onopen = function(evt)
{
onOpen(evt)
};
websocket.onclose = function(evt)
{
onClose(evt)
};
websocket.onmessage = function(evt)
{
onMessage(evt)
};
websocket.onerror = function(evt)
{
onError(evt)
};
}
catch (e)
{
console.log("Exception " + e.toString());
}
}
function onOpen(evt)
{
alert("Connected to " + wsUri);
}
function onClose(evt)
{
alert("Disconnected");
}
function onMessage(evt)
{
alert('Received message : ' + evt.data);
}
function onError(evt)
{
alert("Error : " + evt.toString());
}
function doSend(message)
{
websocket.send(message);
}
window.addEventListener("load", init, false);
</script>
Data is sent from Javascript side using dosend() function.
Few ideas and suggestions.
Check if the client's WebSocket protocol is supported by the server. This question and answer discuss a case where different protocol versions were an issue.
The WebSocket standard permits implementations to arbitrarily delay transmissions and perform fragmentation. Additionally, control frames, such as Ping, do not support fragmentation, but are permitted to be interjected. These permitted behavioral difference may be contributing to the difference in times.
Check if the bufferedAmount attribute on the WebSocket to determine if the WebSocket is buffering the data. If the bufferedAmount attribute is often zero, then data has been passed to the OS, which may be buffering it based on OS or socket configurations, such as Nagle.
This question and answer mentions resolving delays by having the server send acknowledgements for each message.
To get a deeper view into the interactions, it may be useful to perform a packet trace. This technical Q&A in the Mac Developer Library may provide some resources as to how to accomplish this.
The best way to get some more insight is to use the AutobahnTestsuite. You can test both clients and servers with that suite and find out where problems are situated.
I have created QWebSockets, a Qt based websockets implementation, and used that on several occasions to create servers. Performance from Apple devices is excellent.
However, there seems to be a severe problem with Safari when it comes to large messages (see https://github.com/KurtPattyn/QWebSockets/wiki/Performance-Tests). Maybe that is the problem.

Cannot open web socket

I was trying to write a piece of code to open web socket.
var ws = null;
var close = function() {
if (ws) {
console.log('closing ...');
ws.close();
}
}
var onOpen = function() {
console.log('opening...');
ws.send('hello. im connected');
};
var onClose = function() {
console.log('closed');
};
var onMessage = function(event) {
var data = event.data;
console.log('message: ' + data);
};
close();
var url = 'ws://localhost:9999';
ws = new WebSocket(url);
ws.onopen = onOpen;
ws.onclose = onClose;
ws.onmessage = onMessage;
console.log('ws: ' + ws);
if (ws)
{
console.log('url:' + ws.url);
console.log('readyState:' + ws.readyState);
ws.send(msg);
}
else
alert('no ws');
But when seeing the console, the readyState was keep being "CONNECTING", which causes the socket send() command throwing exception.
I tried the extension https://chrome.google.com/extensions/detail/pfdhoblngboilpfeibdedpjgfnlcodoo and get the same issue. The server is pretty simple that accepts incoming socket and write out to console.
There's initial hand shaking but the client's readyState still kept being 0.
Here is the hand shaking:
GET / HTTP/1.1
Upgrade: WebSocket
Connection: Upgrade
Host: localhost:9999
Origin: http://localhost:8080
Sec-WebSocket-Key1: Qb 15 05 6 Gq 9 26 u0 6
Sec-WebSocket-Key2: 8096 C0587|7.
Do i have anything specific in the server to let the client be opened?
Thanks guys.
Your block showing the handshake is incomplete. There should be a blank line followed by 8 bytes of extra data (or key3).
The server needs to construct a return handshake that will look something like:
HTTP/1.1 101 Web Socket Protocol Handshake\r
Upgrade: WebSocket\r
Connection: Upgrade\r
Sec-WebSocket-Origin: http://localhost:8080\r
Sec-WebSocket-Location: ws://localhost:9999/\r
Sec-WebSocket-Protocol: sample\r
\r
[16 byte md5 hash]
The 16 byte hash that the server returns is calculated as follows:
take the numbers from the key1 data and convert them to a number. Divide this number by the number of spaces the key1 data. This gives you a 4 byte key1 number.
do the same thing to the key2 data to get a key2 number.
create a 16 byte array by packing in key1 number (4 bytes) followed by key2 number (4 bytes) followed by the 8 bytes of extra data received from the client (8 bytes).
md5 sum the 16 byte array to get a new 16 byte array. This is what is written to the client to finish the handshake response.
Until the server returns a handshake the client will show "CONNECTING".
The server handshake response is described in more detail in section 5.2 of the WebSockets version 76 standards document
Update based on second question (in the answer section):
If all you are trying to do is send data from an extension then you might consider just using a XMLHttpRequest (AJAX) POST request. Since you are getting anything back from the request I suspect latency is not that important for your application. XMLHttpRequest should be easily support for extensions for both firefox and Chrome.
On the other hand, if latency is important, or if your server where the data is being sent is purely a socket server, adding WebSockets support wouldn't be that much more difficult than adding HTTP support (actually, might be easier). And WebSockets support should also be support for extensions in both Chrome and firefox (4.0 and onwards).
Thanks.
I didn't know that this is 2 ways communication.
I was coding an Chrome extension, that opens a socket and send data to a specific application. I made it worked with FF, using below socket:
var transportService = Components.classes["#mozilla.org/network/socket-transport-service;1"].getService(Components.interfaces.nsISocketTransportService);
var transport = transportService.createTransport(null,0,"localhost",9999,null);
Is there a way that uses similar approach on Chrome? or I have to use WebSocket with 2 ways communication? I dont want to make it complex as I have to modify the receiver application to return a handshake.
Thanks.

Categories