更新时间:2024-12-19 GMT+08:00
分享

QingTian Enclave网络代理工具

QingTian Enclave网络代理工具(qproxy)概述

qproxy(QingTian Enclave proxy)是QingTian Enclave的网络代理工具。借助此工具,您可以无需任何改动,直接将部署在基于QingTian架构虚拟机中的网络业务移植到QingTian Enclave中,实现传统网络业务的无感迁移。

qproxy是一个可执行的二进制文件,需要在父虚拟机和QingTian Enclave中通过不同的命令运行:

  • 在父虚拟机中,通过执行“/path/to/qproxy host --config=/path/to/config_qproxy.toml <cid>”命令启用qproxy。
  • 在QingTian Enclave中,通过执行“/path/to/qproxy enclave --config=/path/to/config_qproxy.toml”命令启用qproxy。

以一个简单的网络服务为例,网络服务直接部署在虚拟机中,负责处理来自最终用户的请求。最终用户通过该服务暴露的端口,发起网络请求,等待服务响应。在将该网络服务迁移至QingTian Enclave之后,通过qproxy代理,可以提供和原本网络服务相同的服务。

使用同一个qproxy二进制文件,通过qlog hostqlog enclave命令,使其分别运行在父虚拟机和QingTian Enclave中,两者会建立基于local vsock的通信链路。父虚拟机中的qproxy组件会监听5050端口,接收用户请求,并通过local vsock将收到的请求转发给QingTian Enclave中的qproxy组件。该组件会将请求发送到QingTian Enclave中监听的5050端口。网络服务处理完成之后,响应数据会原路返回。

图1 网络服务无感迁移至QingTian Enclave

本文介绍qproxy的使用案例。

前提条件

  1. 获取qproxy源码。

    克隆QingTian Enclave代码仓。

    git clone https://gitee.com/HuaweiCloudDeveloper/huawei-qingtian.git
  2. 获取cargo工具链。
    1. 执行以下命令安装rustup。
      curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
    2. 安装完成后执行以下命令加载rustup。
      source $HOME/.cargo/env
    3. 执行以下命令验证rustc和cargo安装成功。
      rustc -V
      cargo -V
  3. qproxy的前置依赖。
    表1 前置依赖

    依赖项

    最低测试版本

    cargo

    1.77.0

    libcbor

    0.10.2

    libssl (libcrypto)

    3.0.0

    libcurl

    4.0.0

  4. QingTian Enclave的环境准备。
    1. 安装qt CLI工具和其他必要rpm包。
    2. 安装Docker。
    3. 安装python3以及几个必要的python module : docker和knack。

    详细内容,请参考快速入门安装qt CLI

使用案例

  1. 构建qproxy

    生成的qproxy程序在目录qingtian-tools/qproxy/target/release下。

  2. 创建工作目录

    新建工作目录workspace,将qproxy程序拷贝到workspace下,后续创建的文件都放在workspace中。

  1. 配置config_qproxy.toml

    在workspace目录中创建config_qproxy.toml文件,内容如下:

    [[inbound_connections]]
    host_port = 5050 
    enclave_port = 5050 
    vsock_port = 9995  
    
    [[inbound_connections]]
    host_port = 5443 
    enclave_port = 5443 
    vsock_port = 9994  
    
    [log_location]
    host_log = "host.log" # qproxy host log name, e.g./var/log/qproxy/host.log
    enclave_log = "enclave.log" # qproxy enclave log name, e.g./var/log/qproxy/enclave.log
    log_level = "info" # qproxy logger level, e.g. "off", "info", "warn", "error", "debug", "trace"
    host_log_dir = "/var/log/qproxy" # qproxy host log dir, and its default value is "/var/log/qproxy"
    enclave_log_dir = "/var/log/qproxy" # qproxy enclave log dir, and its default value is "/var/log/qproxy"

  2. 制作含qproxy的QingTian Enclave镜像

    1. 在workspace目录中创建http请求测试脚本app.sh:
      #!/bin/bash 
      
      PORT=5050 
      
      while true; do    
           echo -e "HTTP/1.1 200 OK\nContent-Type: text/plain\n\nHello world!" | nc -l 127.0.0.1  $PORT
      done
    2. 赋予app.sh执行权限,在workspace目录中执行以下命令:
      chmod +x app.sh
    3. 在workspace目录中创建start.sh脚本:
      #!/bin/bash
      ip link set lo up 
      /root/qproxy enclave --config=/root/config_qproxy.toml &
      /root/app.sh
    4. 赋予start.sh执行权限,在workspace目录中执行以下命令:
      chmod +x start.sh
    5. 在workspace目录中创建Dockerfile文件:
      FROM ubuntu:latest 
      COPY ./qproxy /root/qproxy 
      COPY ./config_qproxy.toml /root/config_qproxy.toml 
      COPY ./start.sh /root/start.sh 
      COPY ./app.sh /root/app.sh 
      RUN apt-get update && \    
          apt-get install -y netcat-openbsd && \    
          apt-get install -y iproute2 
      CMD "/root/start.sh"
    6. 制作docker镜像,在workspace目录中运行以下命令:
      docker build -f Dockerfile -t test_qproxy_enclave .
    7. 制作QingTian Enclave镜像,在workspace目录中运行以下命令:
      qt enclave make-img --docker-uri test_qproxy_enclave --eif test_qproxy_enclave.eif

  3. 启动qproxy

    1. 启动一台QingTian Enclave,在workspace目录中运行以下命令:
      qt enclave start --cpus 2 --mem 1024 --cid 4 --eif test_qproxy_enclave.eif
    2. 启动父虚拟机中的qproxy,在workspace目录中运行以下命令:
      ./qproxy host --config=./config_qproxy.toml 4 &
    3. 父虚拟机中执行curl命令:
      curl localhost:5050

      可以看到终端输出"Hello world!"。

  4. qproxy环境变量设置

    qproxy包含两部分子命令,一部分在QingTian Enclave(qproxy enclave)中运行,另一部分在父虚拟机(qproxy host)中运行。

    通过设置环境变量RUST_LOG可以控制二进制文件的日志输出信息等级。

    • 设置RUST_LOG=OFF,日志信息会全部关闭不显示。
    • 设置RUST_LOG=info,日志信息会显示info,warn和error三个级别的信息。
    • 默认情况下,只会显示warn和error两个级别的日志信息。
    • 可以通过查看EnvFilter文档获取更多信息。

qproxy帮助信息

qproxy help

$ qproxy --help
Usage: qproxy <COMMAND> 

Commands:   
   host          The part of qproxy that runs outside the enclave   
   enclave       The part of qproxy that runs inside the enclave   
   check-config  Check the qproxy configuration file  
   help          Print this message or the help of the given subcommand(s) 

Options:   
   -h, --help     Print help  
   -V, --version  Print version

qproxy enclave help

$ qproxy enclave --help
The part of qproxy that runs inside the enclave  

Usage: qproxy enclave [OPTIONS] 

Options:       
      --parent-cid <PARENT_CID>          
          The CID of the parent VM of this enclave                      

          [env: QPROXY_PARENT_CID=]          
          [default: 3]       

      --config <CONFIG>          
           Path to the configuration file   

  -t, --threads <THREADS>          
           Number of threads the async runtime is allowed to use                      

           [env: TOKIO_WORKER_THREADS=]       

       --control-port <CONTROL_PORT>          
            The port where to listen for control messages from the enclave                      

            Leave at default value unless you know what you are doing                      

            [env: QPROXY_CONTROL_PORT=]          
            [default: 6666]          
            [0..=65535]   

  -h, --help          
            Print help (see a summary with '-h')

qproxy host help

$ qproxy host --help
The part of qproxy that runs outside the enclave  

Usage: qproxy host [OPTIONS] <CID> 

Arguments:   
  <CID>          
           The CID of the enclave                      

           [env: QPROXY_LISTEN_CID=] 

Options:       
        --config <CONFIG>          
             Path to the configuration file   

  -t, --threads <THREADS>          
             Number of threads the async runtime is allowed to use                      

             [env: TOKIO_WORKER_THREADS=]       

      --ipv4          
          Only resolve IPv4 addresses        

      --ipv6          
          Only resolve IPv6 addresses        

      --control-port <CONTROL_PORT>          
          The port where to listen for control messages from the enclave                      

          Leave at default value unless you know what you are doing                      

          [env: QPROXY_CONTROL_PORT=]          
          [default: 6666]          
          [0..=65535]   

  -h, --help          
          Print help (see a summary with '-h')

配置信息(Config)

配置参数解释

  • outbound_connections:用于配置QingTian Enclave中业务和外部IP地址网络端口通信。
  • inbound_connections:用于配置QingTian Enclave中业务和父虚拟机进行网络端口通信。
表2 配置参数解释

Bound

Variable

Type

Description

outbound_connections

hostname

String

用于转发流量的主机名(hostname),可以是IP地址,例如:hostname = "api.myservice.com"。

vsock_port

u32

QingTian Enclave内vsock要使用的端口,必须唯一,并且不能和qproxy端口冲突。

tcp_port

u32

服务器转发流量的端口(将连接到hostname:port),同一端口将暴露在QingTian Enclave中,不能和qproxy端口冲突(默认是8080)。

inbound_connections

host_port

u32

主机端(host)qproxy将会监听的端口,如host_port = 80,主机端qproxy将会监听0.0.0.0:80。

enclave_port

u32

QingTian Enclave端qproxy将会监听的端口,如enclave_port = 80,QingTian Enclave端qproxy将会监听127.0.0.1:80。

vsock_port

u32

QingTian Enclave内vsock要使用的端口,必须唯一,并且不能和qproxy端口冲突。

日志文件配置

表3 日志文件配置

Variable

Type

Description

host_log

String

qproxy在主机端(host)日志文件名称, 例如:host_log = "host.log"表示主机端(host)qproxy日志文件名为host.log。

enclave_log

String

qproxy在QingTian Enclave端日志文件名称,例如:enclave_log = "enclave.log"表示QingTian Enclave中qproxy日志文件名为enclave.log。

log_level

String

qproxy日志级别, 例如:log_level = "info"表示显示信息,警告和错误。全部级别有 "off", "info", "warn", "error", "debug", "trace"。

host_log_dir

String

qproxy在主机端(host)日志目录,默认是 "/var/log/qproxy"

enclave_log_dir

String

qproxy在QingTian Enclave端日志目录,默认是 "/var/log/qproxy"

配置文件参考

[[outbound_connections]]
hostname = "api.myservice.com" 
vsock_port = 7777 
tcp_port = 443  

[[outbound_connections]]
hostname = "another.api.com" 
vsock_port = 7778 
tcp_port = 5555  

[[inbound_connections]]
host_port = 80  
enclave_port = 80  
vsock_port = 9000   

[[inbound_connections]]
host_port = 443 
enclave_port = 443 
vsock_port = 9001  

[log_location]
host_log = "host.log"  
enclave_log = "enclave.log"  
log_level = "info"  
host_log_dir = "/var/log/qproxy"  
enclave_log_dir = "/var/log/qproxy"

相关文档