Como posso detectar se o usuário está em localhost no PHP?

99

Em outras palavras, como posso saber se a pessoa que usa meu aplicativo da web está no servidor em que reside? Se bem me lembro, PHPMyAdmin faz algo assim por razões de segurança.

Richie Marquez
fonte

Respostas:

177

Você também pode usar $_SERVER['REMOTE_ADDR']para qual endereço IP da solicitação do cliente é fornecido pelo servidor da web.

$whitelist = array(
    '127.0.0.1',
    '::1'
);

if(!in_array($_SERVER['REMOTE_ADDR'], $whitelist)){
    // not valid
}
mauris
fonte
2
O que tornaria isso realmente mais fácil de quebrar do que falsificar o IP. Você realmente deveria mudar isso.
Pekka
3
@ skcin7 pode ser a configuração do seu servidor. verifique-o.
mauris
4
@Pekka 웃 você pode simplesmente enviar, por exemplo, Host: 127.0.0.1e ele será preenchido HTTP_HOST, portanto, não é um método confiável.
Dejan Marjanović
4
Sim, este é um conselho ruim e em sua forma atual e precisa ser editado - ou votado contra ele.
Pekka
3
Não se esqueça do IPv6:$whitelist = array('127.0.0.1', '::1');
CrazyMax
26

Como complemento, como função ...

function isLocalhost($whitelist = ['127.0.0.1', '::1']) {
    return in_array($_SERVER['REMOTE_ADDR'], $whitelist);
}
Jens Törnell
fonte
5
Como boa prática, eu recomendaria adicionar "else return false;" para que a função sempre retorne um valor booleano. Ou alternativamente, apenas remova o "if" completamente e ao invés "return in_array ($ _SERVER ['REMOTE_ADDR'], $ whitelist);"
Joe Irby
15

Usuários mais novos do sistema operacional (Win 7, 8) também podem achar necessário incluir um endereço remoto de formato IPV6 em sua lista de permissões:

$whitelist = array('127.0.0.1', "::1");

if(!in_array($_SERVER['REMOTE_ADDR'], $whitelist)){
    // not valid
}
rgdigital
fonte
14

$_SERVER["REMOTE_ADDR"]deve informar o IP do usuário. É spoofable, no entanto.

Verifique esta pergunta generosa para uma discussão muito detalhada.

Acho que o que você lembra com PHPMyAdmin é algo diferente: muitos servidores MySQL são configurados de forma que só possam ser acessados ​​do host local por motivos de segurança.

Pekka
fonte
É importante notar que alguns servidores MySQL são configurados dessa forma por não serem vinculados a uma interface pública. Da mesma forma, se você quiser restringir um aplicativo PHP da mesma maneira, deve considerar servi-lo por meio de uma instância do apache ligada apenas a uma interface interna.
Frank Farmer
8

Sinto muito, mas todas essas respostas parecem terríveis para mim. Eu sugeriria reformular a pergunta porque, de certo modo, todas as máquinas são "localhost".

A pergunta deve ser; Como executo caminhos de código diferentes, dependendo da máquina em que ele é executado.

Na minha opinião, a maneira mais fácil é criar um arquivo chamado DEVMACHINE ou o que você realmente quiser e então simplesmente verificar

file_exists ('DEVMACHINE')

Lembre-se de excluir este arquivo ao enviar para o ambiente de hospedagem ao vivo!

Esta solução não depende da configuração da rede, não pode ser falsificada e torna mais fácil alternar entre a execução de "live-code" e "dev-code".

Daniklad
fonte
6

Não parece que você deva usar $_SERVER['HTTP_HOST'], porque este é o valor no cabeçalho http, facilmente falsificado.

Você também pode usar $_SERVER["REMOTE_ADDR"], este é o valor mais seguro, mas também é possível falsificar. Este remote_addré o endereço para onde o Apache retorna o resultado.

nicola
fonte
REMOTE_ADDRé possível falsificar, porém, se você quiser fingir como 127.0.0.1ou ::1, isso requer comprometer a máquina, em que o spoofing REMOTE_ADDRé a menor de suas preocupações. Resposta relevante - stackoverflow.com/a/5092951/3774582
Goose
1

Se você deseja ter uma whitelist / allowlist que suporte IPs estáticos e nomes dinâmicos .

Por exemplo:

$whitelist = array("localhost", "127.0.0.1", "devel-pc.ds.com", "liveserver.com");
if (!isIPWhitelisted($whitelist)) die();

Desta forma, você pode definir uma lista de nomes / IPs que poderão (com certeza) ser detectados. Os nomes dinâmicos adicionam mais flexibilidade para acessar de diferentes pontos.

Você tem duas opções comuns aqui, você pode definir um nome em seu arquivo de hosts local ou você pode apenas usar um provedor de nome dinâmico que pode ser encontrado em qualquer lugar.

Esta função CACHES resulta porque gethostbyname é uma função muito lenta.

Para este propósito, implementei esta função:

function isIPWhitelisted($whitelist = false)
{
    if ( isset($_SESSION) && isset($_SESSION['isipallowed']) )
        { return $_SESSION['isipallowed'];  }

    // This is the whitelist
    $ipchecklist = array("localhost", "127.0.0.1", "::1");
    if ($whitelist) $ipchecklist = $whitelist;

    $iplist = false;
    $isipallowed = false;

    $filename = "resolved-ip-list.txt";
    $filename = substr(md5($filename), 0, 8)."_".$filename; // Just a spoon of security or just remove this line

    if (file_exists($filename))
    {
        // If cache file has less than 1 day old use it
        if (time() - filemtime($filename) <= 60*60*24*1)
            $iplist = explode(";", file_get_contents($filename)); // Read cached resolved ips
    }

    // If file was not loaded or found -> generate ip list
    if (!$iplist)
    {
        $iplist = array(); $c=0;
        foreach ( $ipchecklist as $k => $iptoresolve )
        {
            // gethostbyname: It's a VERY SLOW function. We really need to cache the resolved ip list
            $ip = gethostbyname($iptoresolve);
            if ($ip != "") $iplist[$c] = $ip;
            $c++;
        }

        file_put_contents($filename, implode(";", $iplist));
    }

    if (in_array($_SERVER['REMOTE_ADDR'], $iplist)) // Check if the client ip is allowed
        $isipallowed = true;

    if (isset($_SESSION)) $_SESSION['isipallowed'] = $isipallowed;

    return $isipallowed;
}

Para melhor confiabilidade, você poderia substituir $ _SERVER ['REMOTE_ADDR'] pelo get_ip_address () que @Pekka mencionou em seu post como "esta questão de recompensa"

Heroselohim
fonte
1
Não sei por que alguém definiu uma pontuação negativa para minha resposta enquanto ela claramente oferece resolução de nomes dinâmica e outras não. A resolução de DNS é lenta, por isso as resoluções de cache são necessárias.
Heroselohim
1

Que tal comparar $_SERVER['SERVER_ADDR'] === $_SERVER['REMOTE_ADDR']para determinar se o cliente está na mesma máquina que o servidor?

Eugen Wesseloh
fonte
$_SERVER['SERVER_ADDR']nem sempre retorna o endereço do servidor de forma confiável, por exemplo, se estiver usando balanceadores de carga, ele retorna o endereço IP do balanceador de carga que eu acredito.
Mike W
-2

Eu encontrei uma resposta fácil.

Porque todas as unidades locais têm C: ou D: ou F: ... etc.

Apenas detecte se o segundo caractere é um:

if ( substr_compare(getcwd(),":",1,1) == 0)
{
echo '<script type="text/javascript">alert(" The working dir is at the local computer ")</script>';
    $client_or_server = 'client';
}
else
{
echo '<script type="text/javascript">alert(" The working dir is at the server ")</script>';
    $client_or_server = 'server';
}
Scoobeedo Cool
fonte