php fsockopen介绍

fsockopen — 打开一个网络连接或者一个Unix套接字连接。

语法:

resource fsockopen  ( string $hostname  [, int $port  = -1  [, int &$errno  [, string &$errstr  [, float $timeout  = ini_get(\"default_socket_timeout\")  ]]]] )

参数:

  1. hostname 如果安装了OpenSSL,那么你也许应该在你的主机名地址前面添加访问协议ssl://或者是tls://,从而可以使用基于TCP/IP协议的SSL或者TLS的客户端连接到远程主机。 
  2. port 端口号。如果对该参数传一个-1,则表示不使用端口,例如unix://。 
  3. errno 如果errno的返回值为0,而且这个函数的返回值为 FALSE ,那么这表明该错误发生在套接字连接(connect())调用之前,导致连接失败的原因最大的可能是初始化套接字的时候发生了错误。 
  4. errstr 错误信息将以字符串的信息返回。 
  5. timeout 设置连接的时限,单位为秒。

返回值:

fsockopen() 将返回一个文件句柄,之后可以被其他文件类函数调用(例如: fgets() , fgetss() , fwrite() , fclose() 还有 feof() )。如果调用失败,将返回 FALSE 。 

 

php fsockopen使用案例

1、fsockopen 来模拟生成 HTTP 连接

$fp = fsockopen(\"www.manongjc.com\", 80, $errno, $errstr, 30);
if (!$fp)
{
    echo \"$errstr ($errno)<br />\\n\";
}
else
{
    $out = \"GET / HTTP/1.1\\r\\n\";
    $out .= \"Host: www.manongjc.com\\r\\n\";
    $out .= \"Connection: Close\\r\\n\\r\\n\";
    fwrite($fp, $out);
	$content = \'\';
    while (!feof($fp))
    {
        $content .= fgets($fp, 128);
    }
	echo $content;
    fclose($fp);
}

运行结果:

HTTP/1.1 200 OK
Date: Sun, 26 Jan 2014 01:41:56 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 44177
Connection: close
Vary: Accept-Encoding
Cache-Control: public, max-age=104
Expires: Sun, 26 Jan 2014 01:43:33 GMT
Last-Modified: Sun, 26 Jan 2014 01:41:33 GMT
X-AspNetMvc-Version: 3.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
X-UA-Compatible: IE=10

 

2、PHP fsockopen模拟POST/GET方法

fsockopen除了像上面实例模拟生成 HTTP 连接之外,还能实现很多功能,比如模拟post 和 get 传送数据的方法。

//fsocket模拟post提交
$url = \"http://localhost/test2.php?site=www.manongjc.com\";
print_r(parse_url($url));

//echo $query;
sock_get($url,\"user=gonn\");
//sock_get($url, $query);

//fsocket模拟get提交
function sock_get($url, $query)
{
	$data = array(
	\'foo\'=>\'bar\', 
	\'baz\'=>\'boom\', 
	\'site\'=>\'www.manongjc.com\', 
	\'name\'=>\'nowa magic\'); 
	
	$query_str = http_build_query($data);
	
    $info = parse_url($url);
    $fp = fsockopen($info[\"host\"], 80, $errno, $errstr, 3);
    //$head = \"GET \".$info[\'path\'].\"?\".$info[\"query\"].\" HTTP/1.0\\r\\n\";
	$head = \"GET \".$info[\'path\'].\"?\".$query_str.\" HTTP/1.0\\r\\n\";
    $head .= \"Host: \".$info[\'host\'].\"\\r\\n\";
    $head .= \"\\r\\n\";
    $write = fputs($fp, $head);
    while (!feof($fp))
    {
        $line = fread($fp,4096);
        echo $line;
    }
}

sock_post($url,\"user=gonn\");

function sock_post($url, $query)
{	
    $info = parse_url($url);
    $fp = fsockopen($info[\"host\"], 80, $errno, $errstr, 3);
    $head = \"POST \".$info[\'path\'].\"?\".$info[\"query\"].\" HTTP/1.0\\r\\n\";
    $head .= \"Host: \".$info[\'host\'].\"\\r\\n\";
    $head .= \"Referer: http://\".$info[\'host\'].$info[\'path\'].\"\\r\\n\";
    $head .= \"Content-type: application/x-www-form-urlencoded\\r\\n\";
    $head .= \"Content-Length: \".strlen(trim($query)).\"\\r\\n\";
    $head .= \"\\r\\n\";
    $head .= trim($query);
    $write = fputs($fp, $head);
    while (!feof($fp))
    {
        $line = fread($fp,4096);
        echo $line;
    }
}

接收页面 test2.php 的代码为:

$data = $_REQUEST;

echo \'<pre>\';
print_r( $data );
echo \'</pre>\';

 

3、fsockopen以Socket方式模拟HTTP下载文件

fsockopen的功能很强大,比如前面模拟 HTTP 访问,模拟 POST/GET 请求,下面向大家介绍fsockopen模拟HTTP下载文件

# Socket 模拟HTTP协议传输文件
# Http是应用层协议使用端口80
#
$hostname = \'www.nowamagic.net\';
$port = \'80\';
# 建立连接
$fp = fsockopen($hostname,$port,$errno,$errstr);
//set_socket_blocking($fp,false);
//stream_set_blocking($fp,0);
stream_set_blocking($fp, true); 
if(!$fp)
{
    echo \"$errno : $errstr<br/>\";
}
else
{
	# 发送一个HTTP请求信息头
    $request_header=\"GET /librarys/webapp/Snow.zip HTTP/1.1\\n\";
	# 起始行
	# 头域
    $request_header.=\"Host: $hostname\\n\";
	# 再一个回车换行表示头信息结束
    $request_header.=\"\\n\";

	# 发送请求到服务器
    fputs($fp,$request_header);
	# 接受响应
    $fp2=fopen(\'Snow.zip\',\'w\');
    while (!feof($fp))
    {
        $line = fputs($fp2,fgets($fp,128));
		//echo $line;
    }
	# 关闭
    fclose($fp2);
    fclose($fp);
}

执行程序,你会发现在这个程序文件的同级目录就会出现那个你需要下载的文件了。

这实质上是 Socket 模拟HTTP协议传输文件。同时还要注意一下 PHP 的超时限制,这里设置我 PHP 服务器超时为无限才能正确下载,否则可能下载不全 PHP 程序就停止了。

 

4、使用 fsockopen 伪造来路

记得以前我们讲解了《php 伪造HTTP_REFERER页面URL来源的三种方法》,里面有一种方法就是使用到fsockopen,具体实现代码如下:

$host = \"127.0.0.1\"; //你要访问的域名
$ip = \'127.0.0.1\';
$target = \"/test2.php\"; //你要访问的页面地址
$referer = \"http://www.manongjc.com/\"; //伪造来路页面
//$fp = fsockopen($host, 80, $errno, $errstr, 30);
$fp = fsockopen($ip, 80, $errno, $errstr, 5);
if(!$fp)
{
    echo \"$errstr($errno)<br />\\n\";
}
else
{
	$end = \"\\r\\n\";
    $out = \"GET $target HTTP/1.1$end\";
	$out .= \"Host: $ip$end\";
	$out .= \"Referer: $referer$end\";
	$out .= \"Connection: Close$end\";
	$out .= \"$end\";
    fwrite($fp, $out);
    while(!feof($fp))
    {
        echo fgets($fp, 1024);
    }
    fclose($fp);
}

test2.php 的代码为:

$data = $_SERVER;

echo \'<pre>\';
print_r( $data );
echo \'</pre>\';

运行结果:

HTTP/1.1 200 OK
Date: Thu, 13 Feb 2014 08:19:10 GMT
Server: Apache/2.2.21 (Win32) mod_ssl/2.2.21 OpenSSL/1.0.0e PHP/5.3.8 mod_perl/2.0.4 Perl/v5.10.1
X-Powered-By: PHP/5.3.8
Content-Length: 1393
Connection: close
Content-Type: text/html

Array
(
	……
    [HTTP_HOST] => 127.0.0.1
    [HTTP_REFERER] => http://www.manongjc.com/
    [HTTP_CONNECTION] => Close
	……
    [SERVER_SIGNATURE] => 
Apache/2.2.21 (Win32) mod_ssl/2.2.21 OpenSSL/1.0.0e PHP/5.3.8 mod_perl/2.0.4 Perl/v5.10.1 Server at 127.0.0.1 Port 80
    [SERVER_SOFTWARE] => Apache/2.2.21 (Win32) mod_ssl/2.2.21 OpenSSL/1.0.0e PHP/5.3.8 mod_perl/2.0.4 Perl/v5.10.1
    [SERVER_NAME] => 127.0.0.1
    [SERVER_ADDR] => 127.0.0.1
    [SERVER_PORT] => 80
    [REMOTE_ADDR] => 127.0.0.1
    [REMOTE_PORT] => 50404
    [GATEWAY_INTERFACE] => CGI/1.1
    [SERVER_PROTOCOL] => HTTP/1.1
    [REQUEST_METHOD] => GET
    [QUERY_STRING] => 
    [REQUEST_URI] => /test2.php
    [ _NAME] => /test2.php
    [PHP_SELF] => /test2.php
    [REQUEST_TIME] => 1392279550
)

可以看到 HTTP_REFERER 的值为 http://www.manongjc.com/,即来路已经伪造成功。

收藏 打印