欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

PHP+Swoole實(shí)現(xiàn)web版的shell客戶端詳解

 更新時(shí)間:2022年07月27日 10:29:38   作者:PHP開源社區(qū)  
這篇文章主要為大家詳細(xì)介紹了如何利用PHP+Swoole實(shí)現(xiàn)web版的shell客戶端,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以嘗試一下

本來(lái)是想通過PHP的proc_open和進(jìn)程進(jìn)行交互,可是中間的坑太多了,不得不轉(zhuǎn)換一下思路,然后想起來(lái)寶塔有網(wǎng)頁(yè)版shell客戶端,然后研究了一下,嘿嘿,發(fā)現(xiàn)能成 。

一、前期準(zhǔn)備

PHP連接ssh是基于第三方拓展庫(kù),PECL/ssh2( libssh2的php擴(kuò)展,允許php程序調(diào)用libssh2中的函數(shù))

然后有一個(gè)現(xiàn)成的、封裝好大部分常用操作的庫(kù)phpseclib

通過swoole的協(xié)程實(shí)現(xiàn)SSH的讀和寫并發(fā)進(jìn)行以及websocket和瀏覽器進(jìn)行通信。

1、安裝ssh2拓展庫(kù)

1.1、Linux安裝

首先要安裝libssh2(libssh2是一個(gè)C 函數(shù)庫(kù),用來(lái)實(shí)現(xiàn)SSH2協(xié)議。)

yum?install?libssh2?libssh2-devel?

然后通過pcel安裝ssh2拓展 ,找準(zhǔn)版本

pecl install ssh2-1.1.2

當(dāng)然也可以通過phpize進(jìn)行手動(dòng)安裝。

1.2、window安裝

libssh2好像一般都有,沒有就下載丟到系統(tǒng)里,主要是安裝ssh2。根據(jù)自己PHP的版本去下載,可以看下自己的php版本,以及是32位的還是64位的,32位的下載x86, 64位的下載x64

下載地址

php.ini中加入 extension=php_ssh2.dll ,完事。

2、swoole安裝

參考官網(wǎng):https://wiki.swoole.com/#/environment

3、phpseclib

官網(wǎng):https://phpseclib.com,composer安裝即可:

composer?require?phpseclib/phpseclib:~3.0

二、編寫代碼

測(cè)試Demo:http://cname.teiao.com:5707/

通過swoole創(chuàng)建一個(gè)websocket,連接成功時(shí)創(chuàng)建一個(gè)協(xié)程專門讀取ssh返回的內(nèi)容發(fā)送到websocket,客戶端發(fā)送消息時(shí)轉(zhuǎn)發(fā)給shell。

以下是簡(jiǎn)單的功能實(shí)現(xiàn),不可應(yīng)用于生產(chǎn),經(jīng)測(cè)試,實(shí)際使用過程中某些命令的輸出需要進(jìn)行特殊處理。

1、swoole.php

<?php

include_once 'include/functions.php';
include_once 'vendor/autoload.php';

use Swoole\Http\Request;
use Swoole\Http\Response;
use Swoole\WebSocket\CloseFrame;
use Swoole\Coroutine\Http\Server;

use Swoole\Coroutine;
use function Swoole\Coroutine\go;
use function Swoole\Coroutine\run;
use function Swoole\Coroutine\defer;
use phpseclib3\Net\SSH2;



/*
 * 設(shè)置協(xié)程運(yùn)行相關(guān)的參數(shù)
 * */
Co::set([
    'socket_timeout'=>-1, //tcp超時(shí)
    'hook_flags' => SWOOLE_HOOK_ALL  //HOOK函數(shù)范圍
]);


/*
 * 創(chuàng)建協(xié)程容器
 * */
run(function () {

    /*
     * 第三個(gè)參數(shù) 代表是否開啟ssl
     * */
    $server = new Server('0.0.0.0', 5707, false);

    $server->handle('/ws', function (Request $request, Response $ws) {

        /*websocket協(xié)議*/
        $ws->upgrade();

        /*連接ssh*/
        $ssh = new SSH2('localhost',22);

        /*如果登錄失敗*/
        if (!$ssh->login('root', 'Qq461625091@')) {
            $ws->close();
            return;
        }

        /*命令輸出內(nèi)容的讀取時(shí)間*/
        $ssh->setTimeout(0.1);



        /*
         * 創(chuàng)建協(xié)程,專門輸出命令行內(nèi)容
         * */
        $subscribe=function () use($ws,$ssh){


            /*
             * 保存id,用于取消協(xié)程
             * */
            $ws->Gid = go(function () use ($ws,$ssh){

                /*
                 * 協(xié)程退出時(shí)清理
                 * */
                defer(function () use ($ssh,$ws) {
                    /*
                     * 退出
                     * */
                    logs($ws->qq.',已斷開鏈接!');
                    $ssh->disconnect();
                });


                try {

                    while (true){
                        $msg=$ssh->read('username@username:~$');
                        if(!empty($msg)){
                            $ws->push($msg);
                        }
                    }

                } catch (\Throwable $e) {
                    logs('讀取異常');
                }

            });
        };


        /*
         * 清理
         * */
        $quit=function ($log) use ($ws){

            logs($log);//記錄退出原因

            /*
             * 如果協(xié)程已經(jīng)運(yùn)行
             * */
            if(isset($ws->Gid)){
                Coroutine::cancel($ws->Gid); //關(guān)閉協(xié)程
            }

            $ws->close(); //斷開ws

        };


        /*
         * 正常處理邏輯
         * */

        $subscribe(); //開始訂閱

        $cmd=[
            'ps -ef',
            'ping 127.0.0.1',
            'ifconfig',
            "\x03"
        ];


        while (true) {

            $frame = $ws->recv(); //阻塞接收消息

            if ($frame === '') {

                $quit("斷開連接,收到空數(shù)據(jù)!");
                break;

            } else if ($frame === false) {

                $quit(swoole_last_error());
                break;

            } else {

                if ($frame->data == 'close' || get_class($frame) === CloseFrame::class) {
                    $quit("用戶主動(dòng)關(guān)閉\n");
                    break;
                }

                /*
                  * 如果不在測(cè)試命令,則終止
                  * */
                if(!in_array($frame->data,$cmd)){
                    continue;
                }

                $ssh->write($frame->data."\n"); // note the "\n"

            }
        }
    });


    /*
     * 輸出默認(rèn)測(cè)試模板
     * */
    $server->handle('/', function (Request $request, Response $response) {
        $response->end(getTest());
    });

    $server->start();
});

2、function.php

<?php

/*
 * 打印測(cè)試的html模板
 * */
function getTest(): string
{
    $test = <<<HTML
        <!DOCTYPE html>
        <html lang="zh-cn" xmlns="http://www.w3.org/1999/html">
        <head>
            <meta charset="UTF-8"/>
            <meta charset="UTF-8"/>
            <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
            <title>Web SSH客戶端</title>
            <link  rel="external nofollow"  rel="shortcut icon" type="image/x-icon"/>
            <script src="https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/jquery/3.6.0/jquery.min.js" type="application/javascript"></script>
            <script src="https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/keyboardjs/2.6.2/keyboard.min.js" type="application/javascript"></script>
            <style>
                body{
                    background-color: #000000;
                    color: #e2e2e2;
                    padding: 15px;
                }
                 input{
                    background-color: black;
                    border: none;
                    color: white;
                    outline: none;
                    font-size: 17px;
                }
            </style>
        </head>
        <body>
        <h1>Web SSH測(cè)試</h1>
        <div>須知:測(cè)試環(huán)境只支持:ps -ef、ping 127.0.0.1、ifconfig,三個(gè)命令。</div>
        <div>提示:回車提交、ctrl+c中斷(終端現(xiàn)在連接的是網(wǎng)站的主機(jī))</div>
        <br />
        <main>
             <span id="content"></span>
             <input type="text">
        </main>

        </body>
        <script>

         window.onload=function (){

            let content=$("#content");
            let input= $('input');
            let wsServer = 'ws://cname.teiao.com:5707/ws';
            let websocket = new WebSocket(wsServer);

            websocket.onopen = function (evt) {
                content.append("Connected to WebSocket server.<br />");
            };

            websocket.onclose = function (evt) {
                content.append("Disconnected.<br />");
            };

            websocket.onmessage = function (evt) {
                content.append(evt.data.replaceAll("\\n",'<br />'));
                input.val("");
                $(window).scrollTop(document.documentElement.scrollHeight)  
            };

            websocket.onerror = function (evt, e) {
                content.append("Error occured: " + evt.data+"<br />");
            };


            input.focus();

            /*
            * 自動(dòng)聚焦
            * */
            $(window).on("click",function (){
                input.focus();
            })

            /*
            * 回車提交
            * */
            keyboardJS.bind('enter', (e) => {
              websocket.send(input.val());
            });

            /*
            * ctrl+c
            * */
             keyboardJS.bind('ctrl > c', (e) => {
              websocket.send("\x03");
            });
        }


        </script>
HTML;

    return $test;
}


/*
 * 記錄日志
 * */
function logs(string $log, bool $flag = true): void
{
    $time = date("Y-m-d H:i:s", time());

    if ($flag) {
        echo $time . ',' . $log . "\n";
    } else {
        file_put_contents('log.txt', $time . ',' . $log . "\n", FILE_APPEND);
    }
}

3、運(yùn)行

php swoole.php

以上就是PHP+Swoole實(shí)現(xiàn)web版的shell客戶端詳解的詳細(xì)內(nèi)容,更多關(guān)于PHP Swoole shell客戶端的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論