Skip to content Skip to sidebar Skip to footer

How To Set Websocket Origin Header From Javascript?

I'm trying to use javascript to make a websocket request from a local test.dev page to a server running at ip 123.123.123.123 on behalf of test.com. The request goes through, but t

Solution 1:

The simple solution would be to simply create an entry in your hosts file to map test.com to 123.123.123.123. You would need to remove this entry later when you want to connect the "real" test.com.

A less hacky solution would require the use of a proxy which can re-write your headers for you on-the-fly. Consider install nginx on your system, and then proxing the request to 123.123.123.123 keeping everything the same except for the Origin header. Here's the entry you would need in your nginx config file:

server {
    server_name test.dev;

    location / {
        proxy_pass http://123.123.123.123;
        proxy_set_header Origin test.com;

        # the following 3 are required to proxy WebSocket connections.# See more here: http://nginx.com/blog/websocket-nginx/

        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

Solution 2:

How can I use javascript to start a websocket connection with a dishonest Origin header of Origin: test.com?

If we could forge the origin of requests in JavaScript, the same origin policy wouldn't be very good at keeping us safe. It exists solely to protect us from this and other potential attack vectors.

As this looks like dev work, have you considered using a web debugging proxy such as Fiddler (free) or Charles (paid)? With those you could modify the initial handshake request or response for the WebSocket for your own machine or any test machines that are proxied through the debugger.

Solution 3:

A good solution is to override the WebSocket call with another websocket library, like https://github.com/websockets/ws. To use this node.js library in a browser, you just have to use http://browserify.org/.

Solution 4:

If you really must forge a fake 'origin' header value from javascript - there is a way. Its not something you will find in your generally accepted principles handbook, but here it is:

Create a php file that invokes the socket, with a fake origin value. Now call the php file using ajax, from you javascript.

It may not be elegant, ethical or acceptable, but never accept anyone telling you that it cant be done.

'send.php' was called using ajax from javascript

send.php contents

require"websocket_client.php";
$client = new Client("IP_ADDR:PORT", $_GET[mobile] ."|".$_GET[login]);
$client->send('1112223333|sms');
$client->send(json_encode(array('login'=>$user,'msg'=>$msg)));
echo$client->receive();`enter code here`

websocket_client.php was a class file with basic websocket functions (including the custom origin values

/**


 * Perform WebSocket handshake
   */protectedfunctionconnect() {
    $url_parts = parse_url($this->socket_uri);
    $scheme    = $url_parts['scheme'];
    $host      = $url_parts['host'];
    $user      = isset($url_parts['user']) ? $url_parts['user'] : '';
    $pass      = isset($url_parts['pass']) ? $url_parts['pass'] : '';
    $port      = isset($url_parts['port']) ? $url_parts['port'] : ($scheme === 'wss' ? 443 : 80);
    $path      = isset($url_parts['path']) ? $url_parts['path'] : '/';
    $query     = isset($url_parts['query'])    ? $url_parts['query'] : '';
    $fragment  = isset($url_parts['fragment']) ? $url_parts['fragment'] : '';

$path_with_query = $path;
if (!empty($query))    $path_with_query .= '?' . $query;
if (!empty($fragment)) $path_with_query .= '#' . $fragment;

if (!in_array($scheme, array('ws', 'wss'))) {
  thrownew BadUriException(
    "Url should have scheme ws or wss, not '$scheme' from URI '$this->socket_uri' ."
  );
}

$host_uri = ($scheme === 'wss' ? 'ssl' : 'tcp') . '://' . $host;

// Open the socket.  @ is there to supress warning that we will catch in check below instead.$this->socket = @fsockopen($host_uri, $port, $errno, $errstr, $this->options['timeout']);

if ($this->socket === false) {
  thrownew ConnectionException(
    "Could not open socket to \"$host:$port\": $errstr ($errno)."
  );
}

// Set timeout on the stream as well.
stream_set_timeout($this->socket, $this->options['timeout']);

// Generate the WebSocket key.$key = self::generateKey();

// Default headers (using lowercase for simpler array_merge below).$headers = array(
  'host'                  => $host . ":" . $port,
  'user-agent'            => 'websocket-client-php',
  'connection'            => 'Upgrade',
  'upgrade'               => 'websocket',
  'origin'               =>  $MY_CUSTOM_SHADY_VALUE,
  'sec-websocket-key'     => $key,
  'sec-websocket-version' => '13',
);

// Handle basic authentication.if ($user || $pass) {
  $headers['authorization'] = 'Basic ' . base64_encode($user . ':' . $pass) . "\r\n";
}

// Deprecated way of adding origin (use headers instead).if (isset($this->options['origin'])) $headers['origin'] = $this->options['origin'];

// Add and override with headers from options.if (isset($this->options['headers'])) {
  $headers = array_merge($headers, array_change_key_case($this->options['headers']));
}

$header =
  "GET " . $path_with_query . " HTTP/1.1\r\n"
  . implode(
    "\r\n", array_map(
      function($key, $value) { return"$key: $value"; }, array_keys($headers), $headers
    )
  )
  . "\r\n\r\n";

// Send headers.$this->write($header);

// Get server response.$response = '';
do {
  $buffer = stream_get_line($this->socket, 1024, "\r\n");
  $response .= $buffer . "\n";
  $metadata = stream_get_meta_data($this->socket);
} while (!feof($this->socket) && $metadata['unread_bytes'] > 0);

/// @todo Handle version switching// Validate response.if (!preg_match('#Sec-WebSocket-Accept:\s(.*)$#mUi', $response, $matches)) {
  $address = $scheme . '://' . $host . $path_with_query;
  thrownew ConnectionException(
    "Connection to '{$address}' failed: Server sent invalid upgrade response:\n"
    . $response
  );
}

$keyAccept = trim($matches[1]);
$expectedResonse
  = base64_encode(pack('H*', sha1($key . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));

if ($keyAccept !== $expectedResonse) {
  thrownew ConnectionException('Server sent bad upgrade response.');
}

$this->is_connected = true;

}

Post a Comment for "How To Set Websocket Origin Header From Javascript?"