[API] Authenticating a server request
#1

I have a web API that processes HTTP requests from SA-MP Servers. On my web API, I have a list of servers (in a database). When a server sends a request to my API, the API will check where the request is coming from (the source IP) and will allow it to perform actions on the server(s) with the same IP.

So let's say a SA-MP server with IP "127.0.01:7777" sends a HTTP(); to my API with some data. My API will check the source (127.0.0.1), look for any servers it has in it's database (could be 127.0.0.1:777, or any other port).

If it finds a match, it will process the request using this IP. This way IP 127.0.0.1 can only do stuff with servers with the same IP. A request coming from 94.126.3.15 can not perform action on a server with IP 94.133.25.5, and vice versa.

An illustration:



All this is based on the fact that, if a request is coming from a SA-MP server with IP X, this server owns the right to control server X on my web API.

I need to establish a secure connetion between a SA-MP server and the server on my web API. Is this the way to go? How do I make sure the request is always coming from the actual server, i.o.w that I know 100% for sure that the request send from a server is actually coming from this server and that the IP or any other data was not spoofed?
Reply
#2

.htaccess
Code:
order deny,allow
deny from all
allow from 127.0.0.1
Reply
#3

Quote:
Originally Posted by rickisme
View Post
.htaccess
Code:
order deny,allow
deny from all
allow from 127.0.0.1
I don't think you fully understand the concept. I'm looking for a way to authenticate requests, not to restrict access to a certain page.
Reply
#4

PHP Code:
<?php
    
function get_ip()
    {
        
# Enable X_FORWARDED_FOR IP matching?
        
$do_check 1;
        
$addrs = array();
        if( 
$do_check )
        {
            foreach( 
array_reverse(explode(','$_SERVER['HTTP_X_FORWARDED_FOR'])) as $x_f )
            {
                
$x_f trim($x_f);
                if( 
preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/'$x_f) )
                {
                    
$addrs[] = $x_f;
                }
            }
            
$addrs[] = $_SERVER['HTTP_CLIENT_IP'];
            
$addrs[] = $_SERVER['HTTP_PROXY_USER'];
        }
        
$addrs[] = $_SERVER['REMOTE_ADDR'];
        foreach( 
$addrs as $v )
        {
            if( 
$v )
            {
                
preg_match("/^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/"$v$match);
                
$ip $match[1].'.'.$match[2].'.'.$match[3].'.'.$match[4];
                if( 
$ip && $ip != '...' )
                {
                    break;
                }
            }
        }
        return 
$ip;
    }
    
// List ip allow
    
$list_ip = array(
        
"127.0.0.1"
    
);
    
// Get target ip 
    
$ipget get_ip();
    if ( !
in_array($ipget$list_ip) ){ 
        echo 
"Access Denied !";
        exit();
    }
    else
    {
        
// do some thing ?
    
}
?>
Reply
#5

You could check the source IP addresses using $_SERVER["REMOTE_ADDR"], which cannot be spoofed. Any other IP headers can be easily spoofed, and you shouldn't rely on them.

Alternatively, you could use API keys, which you would include in every request made by the client and verify it on the server side. However, any sensitive data (the key for instance) should be transmitted using SSL encryption (https), which is not supported by SA-MP.
Reply
#6

What Johnson said is true. IP spoofing does not work by spoofing the actual IP (well, unless they have access to said server the IP is registerd to, you should not have to defend against this case).

But instead spoofs headers, REMOTE_ADDR is known to be secure now, but you should definitely use authentication with a public/private key. For this you should establish a secure connection over SSL. You will probably have to write a plugin to do this correctly.

You could use resources like this for guidance, but you're best off just googling it.

http://www.ibm.com/developerworks/we...ary/ws-best11/
https://groups.******.com/forum/#!to...py/Ljg1SnFzgUA
Reply
#7

A pretty simple way would be to, in addition to just checking the IP/port, add a certain unique key with the request.
When adding a new server to your web API, generate a key and put it in the database together with the IP. Then add that key to the server and add it to the post/get data of your request.
Reply
#8

Thank you everyone for your responses.

Quote:
Originally Posted by Johnson_boy
View Post
You could check the source IP addresses using $_SERVER["REMOTE_ADDR"], which cannot be spoofed.
Wow, I did not know that. Thank you I was indeed very worried about IP spoofing.

The script used to send the requests is actually a filterscript that can be downloaded by the users -- they can freely change it if they want -- so I can't append anything to the request when it's being sent (which leaves API keys out). SSL/Public-private keys just doesn't seem user friendly at all. I can only rely on the fact that, if the request does not contain data in a specific format and is not coming from a specific server, it's not a valid request.

So I was working on a variation of API keys in the form of some sort of encrypted payload the user can't replicate. Yes, the extra data needed for the authentication is human-readable, but only in the form of a long random string of characters and they can't actually decrypt it and they can't encrpyt their own data. The only thing they could do is use the script on a different server with the same payload, but that won't work since the remote IP won't match the server IP.

The HTTP function currently looks like this, which seems to work fine:
pawn Code:
new data[] = "453G8GlY5KZxO+u0svQhUPZLUGXz8ala6dc4WYlG9eUpY6mGs4u1yGrXWpBxGOI5";
HTTP(0, HTTP_POST, "my.website.com/sampapi/authenticate", data, "OnHttpResponse");
The API can make sense of this seemingly random string of characters, but (hopefully) nobody else can. Along with security through obscurity it should work okey for what I want it to do. An illustration:



Happy to explain more if it doesn't make sense.
Thoughts?

EDIT: Well I realize now that is actually the very defenition of public/private keys. The users are given the public key, but only the API knows what to do with it.
Reply
#9

Quote:
Originally Posted by Sinner
View Post
EDIT: Well I realize now that is actually the very defenition of public/private keys. The users are given the public key, but only the API knows what to do with it.
Haha

Would be interested to see HTTPS being implemented though. But as long as you're not sending passwords, I suppose you'll be relatively safe.
Reply
#10

Why exactly are the API keys out of question? I didn't quite understand the reason
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)