国产+高潮+在线,国产 av 仑乱内谢,www国产亚洲精品久久,51国产偷自视频区视频,成人午夜精品网站在线观看

請教, 我有100多個ssl證書, 而且數(shù)量會變化, 作為https服務(wù)端怎么根據(jù)每個請求的域名不同, 使用不同的證書呢?

mgzhenhong

能否在 TcpConnection 的 stream_socket_enable_crypto 之前, 提供一個 beforeSslHandshake 回調(diào)方法來修改 socket 的 contentx, 來實現(xiàn)這個功能?

4053 4 3
4個回答

mgzhenhong

看了些資料, SSL在握手階段, 客戶端發(fā)的第一個Hello握手包里有域名, 要實現(xiàn)這個功能, 必須取得這個包里的Extension server_name數(shù)據(jù). 現(xiàn)有的socket和stream函數(shù)好像沒有這樣的功能. 不知道是不是要用openssl自己實現(xiàn)ssl握手過程才行.

  • 暫無評論
six

區(qū)分域名的話看起來要openssl手動ssl握手了,這個難度有點大。

  • mgzhenhong 2019-11-19

    我看了TLS協(xié)議握手過程, 硬編碼肯定可以實現(xiàn), 但是效率存疑.
    況且這么大的東西要完全按照規(guī)范寫到穩(wěn)定健壯, 對我這個小項目就是殺雞用牛刀了, 不太現(xiàn)實.

    下個項目會需要解析TLS握手包, 到時候再看.

mgzhenhong
$ctx = stream_context_create(["ssl" => [
    "local_cert" => "/path/to/cert.pem",
    "SNI_server_certs" => [
        "domain1.com" => "/path/to/domain1.pem",
        "*.domain2.com" => "/path/to/domain2.pem",
        "domain3.com" => "/path/to/domain3.pem"
    ]
]]);

找到一些資料, PHP 5.6以后, stream_socket_server 的 context 可以支持 SNI (Server Name Indication).
這樣的話, 這個問題可以解決一半了, 服務(wù)端可以支持針對不同的域名使用不同的證書.

剩下的問題就是, 證書數(shù)量變化時, 在不重啟 Server 的前提下, 如何平滑地重載 SNI 證書列表.

mgzhenhong

此問題已解決, 目前我這里運行良好. 關(guān)鍵代碼和說明如下:

第一步: 聲明 context, 啟動服務(wù).
$context 的 SNI_server_certs 部分留空, 但最終要將 SNI_server_certs 部分填充為注釋所示的樣子.

$context = [
    'ssl' => [
        'verify_peer'         => false,
        'disable_compression' => true,
        'SNI_enabled'         => true,
        'SNI_server_certs'    => [
            /*
            "*.domain1.com" => [
                'local_cert'          => "{$this->certFileRoot}/domain1.com/_.domain1.com.pem",
                'local_pk'            => "{$this->certFileRoot}/domain1.com/_.domain1.com.key",
            ],
            "*.domain2.com" => [
                'local_cert'          => "{$this->certFileRoot}/domain2.com/_.domain2.com.crt",
                'local_pk'            => "{$this->certFileRoot}/domain2.com/_.domain2.com.key",
            ],
            "domain3.com" => [
                'local_cert'          => "{$this->certFileRoot}/domain3.com/domain3.com.crt",
                'local_pk'            => "{$this->certFileRoot}/domain3.com/domain3.com.key",
            ],
            "www.domain3.com" => [
                'local_cert'          => "{$this->certFileRoot}/domain3.com/www.domain3.com.crt",
                'local_pk'            => "{$this->certFileRoot}/domain3.com/www.domain3.com.key",
            ],
            */
        ],
    ],
];

$server = new WorkerX("http://0.0.0.0:443", $context);
$server->count = 10;
$server->transport = 'ssl';
$server->name = 'Https Server';

第二步: 繼承并重寫 Worker 類, 以便于可以在運行時設(shè)置 stream_context
原Worker類中, 使用一個 protected 的 _context 屬性保存socket上下文, 外部無法直接修改, 所以需要繼承 Worker后,在我們實現(xiàn)的子類中修改.

另外, socket 上下文在php中是一個 resource 類型, 反映到php中可以視為內(nèi)存地址引用. 對此變量的賦值操作不會創(chuàng)建新的對象.

class WorkerX extends \Workerman\Worker
{
    public function contextGetOptions()
    : array
    {
        if(is_resource($this->_context))
        {
            return stream_context_get_options($this->_context);
        }

        return [];
    }

    public function contextSetOptions(array $options)
    : bool
    {
        if(is_resource($this->_context))
        {
            return stream_context_set_option($this->_context, $options);
        }

        return false;
    }
}

第三步: 在$server的onWorkerStart回調(diào)中, 通過Channel注冊事件, 允許外部通知服務(wù)器動態(tài)載入證書信息.
可以啟動另外一個專用的api服務(wù), api服務(wù)接收管理端的調(diào)用后, 發(fā)布 EVENT_REFRESH_CERT 事件, 事件數(shù)據(jù)中標(biāo)明需要重載哪個站點的證書.

$server->onWorkerStart = function($worker)
{
    WorkerDI::init($worker);

    $this->refreshCert($worker, 0);

    \Channel\Client::on('EVENT_REFRESH_CERT', function($eventData) use ($worker)
    {
        $siteId = intval($eventData['site_id']);
        $this->refreshCert($worker, $siteId);
    });
};

private function refreshCert(WorkerX $worker, int $siteId = 0)
{
    $sslContextOptions = $worker->contextGetOptions();

    // 此處通過 $siteId 查詢數(shù)據(jù)庫, 取得站點綁定的域名, 和域名對應(yīng)的證書文件路徑
    $domain = '*.domain1.com';
    $certFilePath = '/path/to/certFile.crt';
    $keyFilePath = '/path/to/certFile.key';

    $sslContextOptions['ssl']['SNI_server_certs'][$domain] = [
        'local_cert' => $certFilePath,
        'local_pk'   => $pkFilePath,
    ];

    $setResult = $worker->contextSetOptions($sslContextOptions);

    echo "設(shè)置" . ($setResult ? "成功" : "失敗") . "\n";
}

刷新頁面, 此時證書已經(jīng)在服務(wù)中生效, 功能完成.

年代過于久遠(yuǎn),無法發(fā)表回答
??