Making cross-domain requests while maintaining original IP address - javascript

My first attempt was to make a reverse proxy in Express which would allow me to request to localhost:3000/request and have it forward to somesite.com/request.
My code was:
var request = require('request');
app.get('/', function(req,res) {
var newurl = 'http://google.com/';
request(newurl).pipe(res);
});
This issue with this, is it changes the IP address of the request, to my server's IP.
My next attempt was JSONP, even though this is an HTML webpage, not a JSON file.
var tag = document.createElement("script");
tag.src = 'http://example.com/search?q=test';
document.getElementsByTagName("head")[0].appendChild(tag);
The error for that was: Uncaught SyntaxError: Unexpected token <

You can certainly get around CORS with a server-side proxy. You can use a pre-built module like node-http-proxy to do that and to handle most of the implementation for you.
However, the target destination site will see the request coming from the IP address of your proxy server and you cannot change that.
A proper proxy will insert headers into the original HTTP request that contains the original browser's IP address and the receiving server could look at those additional headers if it chose to. But, if it only looks at the IP address that the request actually comes from, then it will see the IP address of your proxy server and you can't change that. For data to flow from your proxy to the target destination server and then the request to come back through your proxy and back to the original browser, there will necessarily be a TCP connection between your server and the target destination and the source IP address has to be your server (that's the only way the data can flow back to your server so you can then forward it back to the browser).
As for JSONP, JSONP requires cooperative support from the target server (the requested data has to be sent back in a piece of Javascript that when run will call the desired callback function). If that server doesn't explicitly support JSONP, then you can't use it.

Related

Problem in communicating with Binance exchange in NodeJS web socket

When I execute the following piece of code in the app.js file
const WebSocket = require('ws');
const ws = new WebSocket('wss://stream.binance.com:9443/ws/!miniTicker#arr');
ws.on('message', function (data){
//const result = JSON.parse(data);
console.log(data);
});
I get the following error and I cannot receive data.
10.10.34.34 (what your DNS server resolved stream.binance.com to) is a local IP address! You are not even reaching Binance. It's probably a captive portal or some firewall.
Open that IP address in the browser and check whether you get some sort of web interface that gives you a clue about what is blocking your request. You can also try changing your DNS server to Google (8.8.8.8) or some other public DNS server instead of relying on your router.
Update:
In your comment you mentioned your DNS server is 178.22.122.100 (i.e., shecan.ir). If I try to resolve the domain with that server, I also get nonsensical results (10.10.34.34 and d0::11). According to this book, this is part of Iranian censorship, and your ISP would handle this IP address to show a page about this domain being blocked if you'd open it in a browser.
So, an alternative public DNS server without censorship such as 8.8.8.8, 1.1.1.1 or 9.9.9.9 should help. If this doesn't work then those DNS servers are also blocked by your ISP and you would need to use a VPN or other means of bypassing government censorship.

Restrict PHP API for specific domains which are saved in my database

I have created an API which takes the hostkey or API_KEY and then it validates and gives back JWT token. Everything is working fine, I can't access the restricted routes without Hostkey.
ISSUE
The major issue is that what will happen if someone gives this hostkey to others as it will no longer be protected or it will be misused. So what I want to do is not only validate the hostkey but also validate the domain from which request came from. It is kind of paid service and I really want to restrict is to specific domains. Just like google does with MAP Api as if we add that map key to other domain it throws an error.
The only way to do this is to check the origin and referrer headers.
Unfortunately, server to server this can't be done reliably as the referrer and origin headers would be set by the coder and so can be spoofed easily. For server to server calls you would be better off whitelisting IP addresses that are allowed to make calls to your APIS. In this case use something like How to get Real IP from Visitor? to get the real IP of the server and verify it against whitelisted IPs.
Assuming this is a JS call in browser and not server to server, and that you trust the browser, the only way this can really be done is by verifying the referrer and origin headers. This can still be spoofed with a browser plugin or even with a tool like Postman so I don't recommend it for high security. Here is a PHP example for verifying the origin or referrer.
$origin_url = $_SERVER['HTTP_ORIGIN'] ?? $_SERVER['HTTP_REFERER'];
$allowed_origins = ['example.com', 'gagh.biz']; // replace with query for domains.
$request_host = parse_url($origin_url, PHP_URL_HOST);
$host_domain = implode('.', array_slice(explode('.', $request_host), -2));
if (! in_array($host_domain, $allowed_origins, false)) {
header('HTTP/1.0 403 Forbidden');
die('You are not allowed to access this.');
}
Optionally also CORS headers are good as commented by #ADyson Cross-Origin Request Headers(CORS) with PHP headers
I would like to suggest making a quote or limit for the number of request, so when the paid API reach for 100 request the key will stop working, then the person who paid will not give the key for others. This is not perfect solution, but I would suggest it cause most API services uses it.

something wrong with jsonp data, How to get the data

But it returns -403 why
but when I click that, It comes out this
how can I get the message
The HTTP 403 Forbidden client error status response code indicates that the server understood the request but refuses to authorize it.. After one-line check with Fetch API the answer is: server is not handling Cross Origin Resource Sharing - making cross-origin AJAX is not possible. You can avoid it by using simple local HTTP server (e.g. in Python) to get data from server (e.g. with requests) and self-serve it (e.g. with Flask).
Check it in JS console:
fetch('https://api.bilibili.com/x/web-show/res/loc?jsonp=jsonp&pf=7&id=1695').then(r=>r.json()).then(json=>console.log(json))

How does Electron proxy URLs?

I created a small server which, for now, just outputs the request.url:
const http = require('http');
http.createServer(onRequest).listen(8080);
function onRequest(clientRequest, clientResponse) {
console.log(clientRequest.url);
}
Using the Electron APIs we can set up a proxy: to proxy all the urls through this server.
So, I'm running my server on localhost:8080 and use the --proxy-server http://localhost:8080 to redirect the traffic through my proxy server. This allows me to change some snippets in the HTML and only then render it in Electron.
When I access http://ionicabizau.net the request.url on the server side is http://ionicabizau.net.
How come that we can override the request url in such a way? What does Electron in the background?
First I thought that it just has to do with appending it like this:
http://localhost:8080/http://ionicabizau.net
But actually, that arrives on the server like /http://ionicabizau.net (notice the first slash).
What's the magic that Electron does to change the url of the request object?
When Electron (or anything else) makes an HTTP request, it connects to the target server and port and sends a message like the following:
GET / HTTP/1.1
Host: www.example.com
Most servers interpret this as an HTTP request for the full URL http://www.example.com/. When you specify a proxy server, that affects what server the HTTP client connects to, but it doesn't change the content of the request (so the requested URL is still http://www.example.com/).
So there's really nothing special that Electron needs to do to "override" the request URL... any HTTP client specifies the request URL as part of the message it sends to the server, and this is independent of which server that message is sent to.

Difference between localhost and IP address in Ajax request sending

I have a strange problem with native Ajax request invoking.
I am creating the Ajax object and sending the request like follows:
var xmlHttpObj = new XMLHttpRequest();
....
xmlHttpObj.open("GET","http://192.168.16.254:8080/ajax/demoExample.html",true);
xmlHttpObj.send();
When I access the servlet with the URL something like http://localhost:8080/ajax...,
then I am not able to get the response in the client side. But I can see the response in the server side.
Pretty similar way I invoked the request with
xmlHttpObj.open("GET","http://localhost:8080/ajax/demoExample.html",true);
and my URL is http://192.168.16.254:8080/ajax..., then also I am not able to see the response in my client side.
I know the best way to fix the problem.
I can invoke the request with
xmlHttpObj.open("GET","../ajax/demoExample.html",true);
xmlHttpObj.send();
then I don't have any problem with either localhost or IP address.
But still I think why is the difference between localhost and IP address in ajax requesting.
It's more of a security feature than a problem :
The same origin policy prevents a
document or script loaded from one
origin from getting or setting
properties of a document from another
origin.
localhost and 192.168.16.254 are considered different origins. The same goes for two hostnames that point to the same address as they could (and probably will) point to a different site/application on the same server. AFAIK the only way around this is to use iframe for content or JSONP for json. Although in your case relative URLs is the way to go.

Categories

Resources