如何实现workerman的动态反向代理

admin

域名绑定到workerman服务器,
然后workerman识别 http协议中的域名,
然后系统内部映射域名源站,
新建AsyncTcpConnection(源站)
转发的数据,修改其中的host即可,这样可以实现 访问a.com(ip为workerman),反向代理到B服务器并且回源域名为:b.com, 这样 a.com就能打开b.com的页面

代码如下:

 public function onMessage(TcpConnection $connection, $data)
    {
        // Parse http header.
        list($method, $addr, $http_version) = explode(' ', $data);
        $_headers=explode("\r\n",$data);
        $headers=[];
        foreach ($_headers as $_header){
            $_point=strpos($_header,':');
            if ($_point===false) continue;
            $headers[substr($_header,0,$_point)]=trim(trim(substr($_header,$_point),':'));
        }

        //替换request 中的回源host
        $replace_domain='a.com';
        //源站IP地址,
        $source_ip='123.123.123.123';

        $data=preg_replace('/Host: (.*)/i','Host: '.$replace_domain,$data);
        // Async TCP connection.
        $remote_connection = new AsyncTcpConnection('tcp://'.$source_ip);
        // CONNECT.
        if ($method !== 'CONNECT') {
            $remote_connection->send($data);
            // POST GET PUT DELETE etc.
        } else {
            $connection->send("HTTP/1.1 200 Connection Established\r\n\r\n");
        }

        print_r($data);
        // Pipe.
        $remote_connection ->pipe($connection);
        $connection->pipe($remote_connection);
        $remote_connection->connect();
    }

目前遇到这个问题,chrome第一次访问a.com 确实反向代理了 123.123.123.123的服务器host为b.com。但是,再次刷新浏览器,123.123.123.123 提示无法找到站点,也就是说可能Host替换失效了,并且第二次刷新浏览器没有触发 print_r ()

1845 1 0
1个回答

admin

目前我使用这样的办法解决了,但是不知道后面是会有问题

<?php

namespace app\cdn\process;

use Workerman\Connection\AsyncTcpConnection;
use Workerman\Connection\TcpConnection;

class CdnTcp
{
    public function onConnect(TcpConnection $connection)
    {
    }

    public function onWebSocketConnect(TcpConnection $connection, $http_buffer)
    {
        echo "onWebSocketConnect\n";
    }

    public function onMessage(TcpConnection $connection, $data)
    {
        // Parse http header.
        list($method, $addr, $http_version) = explode(' ', $data);
        $_headers=explode("\r\n",$data);
        $headers=[];
        foreach ($_headers as $_header){
            $_point=strpos($_header,':');
            if ($_point===false) continue;
            $headers[substr($_header,0,$_point)]=trim(trim(substr($_header,$_point),':'));
        }

        //源站IP地址
        $source_ip='123.123.123.123';
        $source_host='www.baidu.com';
        print_r('用户IP:'.$connection->getRemoteAddress().'| 访问域名:'.$headers['Host'] .' | 源站:'.gethostbyname($source_ip).'| 回源域名'.$source_host);

        // Async TCP connection.
        $remote_connection = new AsyncTcpConnection('tcp://'.$source_ip);
        // CONNECT.

        if ($method !== 'CONNECT') {
            //替换request 中的回源host
            $remote_connection->send(CdnTcp::replaceHost($data,$source_host));
            // POST GET PUT DELETE etc.
        } else {
            $connection->send("HTTP/1.1 200 Connection Established\r\n\r\n");
        }

        $remote_connection->onMessage=function (TcpConnection $SourceConn, $SourceData)use ($connection){
            $connection->send($SourceData);
        };

        $remote_connection->onClose = function ($source) use ($connection) {
            $connection->close();
        };

        $remote_connection->onBufferFull = function ($SourceConn) use ($connection) {
            $connection->pauseRecv();
        };

        $remote_connection->onBufferDrain = function ($SourceConn) use ($connection) {
            $connection->resumeRecv();
        };

        $connection->onMessage=function (TcpConnection $ClientConn, $ClientData)use ($remote_connection,$source_host){
            $remote_connection->send(CdnTcp::replaceHost($ClientData,$source_host));
        };

        $connection->onClose = function (TcpConnection $ClientConn) use ($remote_connection) {
            $remote_connection->close();
        };

        $connection->onBufferFull = function (TcpConnection $ClientConn) use ($remote_connection) {
            $remote_connection->pauseRecv();
        };

        $connection->onBufferDrain = function (TcpConnection $ClientConn) use ($remote_connection) {
            $remote_connection->resumeRecv();
        };

        $remote_connection->connect();
    }

    public static function replaceHost(string $data,$host):string
    {
        return preg_replace('/Host: (.*)/i','Host: '.$host,$data);
    }

    public function onClose(TcpConnection $connection)
    {
        echo "onClose\n";
    }

}
年代过于久远,无法发表回答
🔝