OpenWRT(12):uhttpd主要功能以及客户端连接、CGI/Lua/UBUS/UCODE等处理

uhttpd是一个功能全面、轻量级的Web服务器,是Web管理界面LuCI的默认服务器,支持SSL、CGI、Lua。

uhttpd是单线程,但支持多个实例。

1 配置uhttpd

1.1 配置uhttpd

uhttpd配置如下:

Network
    Web Servers/Proxies
        uhttpd
        uhttpd-mod-lua--Lua插件为uHTTPd提供了一个类似于 CGI 的 Lua 运行时接口,使得开发者可以在处理 HTTP 请求时执行 Lua 脚本。这种集成方式允许开发者利用 Lua 的灵活性和强大功能来增强 Web 应用程序的能力,同时保持了与现有 CGI 程序类似的使用模式。
        uhttpd-mod-ubus--提供ubus插件的功能。为 ubus 提供了一个基于 HTTP 协议和 JSON 格式的远程过程调用(RPC)代理。这意味着用户可以通过发送 HTTP 请求,并使用 JSON 格式编码数据,来远程调用 ubus 上的服务和函数。
        uhttpd-mod-ucode--支持ucode脚本功能插件。
LuCI
    3. Application
        luci-app-uhttpd
Libraries
    Networking
        libuhttpd-mbedtls
        libuhttpd-nossl
        libuhttpd-openssl
        libuhttpd-wolfssl

1.2 uhttpd主要功能

uHTTPd 是 OpenWrt 项目中使用的轻量级 Web 服务器,专为嵌入式系统设计。以下是 uHTTPd 支持的一些关键功能:

  1. HTTP 和 HTTPS 服务:uHTTPd 可以提供标准的 HTTP 服务,并且通过配置支持 HTTPS(HTTP over TLS/SSL),以确保数据传输的安全性。

  2. CGI 脚本支持:uHTTPd 支持 CGI(Common Gateway Interface)脚本,允许执行外部程序或脚本,并返回其输出给客户端。

  3. Lua 脚本支持:uHTTPd 内置了对 Lua 脚本语言的支持,可以在服务器上执行 Lua 脚本来生成动态内容。

  4. 模板处理:uHTTPd 支持使用模板来生成 Web 页面,这在动态内容生成中非常有用。

  5. ubus 集成:uHTTPd 可以与 OpenWrt 的 ubus 消息总线系统集成,允许通过 Web 接口与系统服务进行交互。

  6. JSON-RPC 支持:uHTTPd 支持 JSON-RPC 协议,允许通过 JSON 格式进行远程过程调用。

  7. 多实例运行:uHTTPd 可以运行多个实例,每个实例可以监听不同的端口,拥有独立的配置和文档根目录。

  8. 配置文件:uHTTPd 使用配置文件(通常是/etc/httpd.conf)来定义服务器的行为,包括端口、根目录、日志记录等。
  9. 访问控制:uHTTPd 支持基本的访问控制,例如基于 IP 的访问限制。

  10. 目录列表:uHTTPd 可以自动为包含多个文件的目录生成目录列表。

  11. 日志记录:uHTTPd 支持日志记录功能,可以记录访问和错误信息。

  12. 静态内容服务:uHTTPd 可以高效地提供静态内容,如 HTML、CSS、JavaScript 文件和图片。

  13. 自定义错误页面:uHTTPd 允许定义自定义的 404(未找到)和其他 HTTP 错误页面。

  14. URL 重写:uHTTPd 支持 URL 重写规则,可以基于配置重定向请求。

  15. 文件上传:uHTTPd 支持通过 CGI 脚本进行文件上传。

  16. 代理服务器:uHTTPd 可以配置为代理服务器,转发请求到其他服务器。

  17. IPv4 和 IPv6 支持:uHTTPd 支持 IPv4 和 IPv6 协议,可以同时服务于两种类型的网络请求。

1.3 uhttpd相关概念

Lua:Lua 是 OpenWrt 中广泛使用的一种轻量级脚本语言,它以其简洁和高效而闻名,非常适合用于配置和扩展 OpenWrt 系统的功能。

ubus:OpenWrt 的 UBUS(OpenWrt RPC API Server)是一个远程过程调用(RPC)API服务器,它提供了一种机制,允许用户通过各种协议(如HTTP、WebSocket等)与OpenWrt系统进行交互。

ucode:OpenWrt 的 ucode 是一种小型通用脚本语言,其语法与 ECMAScript 类似,可以独立使用,也可以嵌入到宿主应用程序中。ucode 设计的主要目标包括轻松读写 JSON 数据、易于嵌入 C 应用程序、模板功能、通过可加载的本地扩展模块扩展功能,以及一组直接模仿 Perl 5 语言的内置函数。

mbedtls:是一个由ARM维护的轻量级加密库,专为嵌入式系统设计。它提供了SSL/TLS协议的实现、加密库和X.509证书处理库。mbedTLS易于集成和配置,支持多种编译选项和硬件加速,适合资源受限的环境。

openssl:是一个广泛使用的开源加密库,提供了全面的加密功能,包括SSL/TLS协议、证书管理、各种加密算法等。OpenSSL支持多种平台,广泛应用于服务器、桌面和移动设备。

wolfssl:是一个轻量级的SSL/TLS库,专为嵌入式系统和资源受限环境设计。它提供了类似于OpenSSL的API,但更小、更快,且易于集成。wolfSSL支持最新的TLS 1.3和DTLS 1.2标准,以及多种先进的加密算法。

下面分别总资源占用、性能、易用性、支持比较mbedtls、openssl和wolfssl:

  • 资源占用:mbedTLS和wolfSSL相对于OpenSSL来说,更加轻量级,占用资源更少,更适合嵌入式系统。
  • 性能:wolfSSL在某些基准测试中显示出比OpenSSL更好的性能。
  • 易用性:mbedTLS和wolfSSL都提供了简单的API和示例,易于集成和使用,而OpenSSL则提供了更广泛的功能和更复杂的配置选项。
  • 支持:OpenSSL拥有一个成熟的社区和广泛的支持,而mbedTLS和wolfSSL虽然社区较小,但也在增长中,并提供了专业的技术支持。

2 uhttpd启动

执行/etc/init.d/S50uhttpd中脚本,启动uhttpd:

/usr/sbin/uhttpd -f -h /www -r OpenWrt -x /cgi-bin -l /cgi-bin/luci -L /usr/lib/lua/luci/sgi/uhttpd.lua -

uhttpd选项如下:

Usage: uhttpd -p [addr:]port -h docroot
    -f              Do not fork to background
    -c file         Configuration file, default is '/etc/httpd.conf'
    -p [addr:]port  Bind to specified address and port, multiple allowed
    -s [addr:]port  Like -p but provide HTTPS on this port
    -C file         ASN.1 server certificate file
    -K file         ASN.1 server private key file
    -P ciphers      Colon separated list of allowed TLS ciphers
    -q              Redirect all HTTP requests to HTTPS
    -h directory    Specify the document root, default is '.'
    -E string       Use given virtual URL as 404 error handler
    -b string       Use given charset for directory listings, default to UTF-8
    -I string       Use given filename as index for directories, multiple allowed
    -S              Do not follow symbolic links outside of the docroot
    -D              Do not allow directory listings, send 403 instead
    -R              Enable RFC1918 filter
    -n count        Maximum allowed number of concurrent script requests
    -N count        Maximum allowed number of concurrent connections
    -l string       URL prefix for Lua handler
    -L file         Path to Lua handler script, -l and -L may be repeated in pairs
    -o string       URL prefix for ucode handler
    -O file         Path to ucode handler script, -o and -O may be repeated in pairs
    -u string       URL prefix for UBUS via JSON-RPC handler
    -U file         Override ubus socket path
    -a              Do not authenticate JSON-RPC requests against UBUS session api
    -X        Enable CORS HTTP headers on JSON-RPC api
    -e        Events subscription reconnection time (retry value)
    -x string       URL prefix for CGI handler, default is '/cgi-bin'
    -y alias[=path]    URL alias handle
    -i .ext=path    Use interpreter at path for files with the given extension
    -t seconds      CGI, Lua and UBUS script timeout in seconds, default is 60
    -T seconds      Network timeout in seconds, default is 30
    -k seconds      HTTP keepalive timeout
    -A seconds      TCP keepalive timeout, default is unset
    -d string       URL decode given string
    -r string       Specify basic auth realm
    -m string       MD5 crypt given string

3 uhttpd代码走读

uhttpd主要功能:

  • 支持 HTTP/1.0 和 HTTP/1.1 协议,提供基本的 Web 服务功能。
  • 支持 HTTPS,通过 TLS/SSL 协议提供安全的通信。
  • 能够执行 CGI 脚本,为 Web 应用提供动态内容生成的能力。
  • 通过插件支持 Lua 脚本,可以用于处理请求和生成动态内容。
  • 支持与 OpenWrt 的 UBUS 系统集成,提供远程管理功能。
main
  uh_dispatch_add--向服务器的调度系统添加一个新的处理程序。调度系统负责将请求分配给相应的处理程序。此处添加cgi_dispatch用于处理CGI请求。
  init_defaults_pre--在解析配置文件之前,初始化默认的服务器配置。
  uh_config_parse--解析服务器的配置文件(例如/etc/httpd.conf),配置服务器的行为,如认证、索引文件、解释器等。
    uh_auth_add--向服务器添加基于路径的认证信息。
    uh_index_add--设置目录索引文件,如index.html。
    uh_interpreter_add--添加对特定文件扩展名的处理方式,例如为.php文件指定 CGI 解释器。
  init_defaults_post--在解析配置文件之后,进行最后的默认配置初始化。
    uh_index_add
  uh_tls_init--初始化TLS(传输层安全性)支持,用于HTTPS连接。
  uh_plugin_init--加载并调用插件init()初始化服务器插件,可以扩展服务器的功能。uhttpd_lua.so:加载Lua插件,允许使用Lua脚本处理请求。uhttpd_ubus.so:加载UBUS插件,提供对UBUS框架的支持。
    dlopen--加载库文件。
    dlsym--根据符号名找到函数。
    p->init--执行插件的init函数进行初始化。
  run_server--启动服务器的主函数,负责设置事件循环和启动服务器。
    uloop_init
    uh_setup_listeners--设置网络监听器,这些监听器等待客户端连接。
    uh_plugin_post_init--在服务器设置监听器之后,执行插件的post_init()后续初始化操作。
    uloop_run

3.1 CGI

 cgi_dispatch用于处理CGI请求:

struct dispatch_handler cgi_dispatch = {
    .script = true,
    .check_path = check_cgi_path,
    .handle_request = cgi_handle_request,
};

CGI执行流程如下:

cgi_handle_request
  --权限检查,如果失败调用uh_client_error返回403错误。
  uh_create_process--如果权限验证通过,uh_create_process函数被调用来创建一个新的进程,用于执行 CGI 脚本。
    cgi_main
      clearenv
      setenv
      execl
  uh_client_error--如果CGI脚本无法启动,例如因为找不到脚本或权限问题,uh_client_error函数将被调用,向客户端返回一个500错误(Internal Server Error)。

3.2 ubus 

 ubus插件的初始化入口:

struct uhttpd_plugin uhttpd_plugin = {
    .init = uh_ubus_plugin_init,--ubus_connect()创建到ubus的连接上下文;注册ubus_dispatch。
    .post_init = uh_ubus_post_init,
};

ubus作为插件,在初始化时将注册ubus_dispatch。ubus_dispatch用于处理到uhttpd的UBUS请求:

 static struct dispatch_handler ubus_dispatch = {
        .check_url = uh_ubus_check_url,
        .handle_request = uh_ubus_handle_request,
    };

 通过uhttpd对UBUS请求处理如下:

uh_ubus_handle_request
  UH_HTTP_MSG_GET--如果请求方法是GET,函数将调用uh_ubus_handle_get来处理请求。
    uh_ubus_handle_get
  UH_HTTP_MSG_POST--如果请求方法是POST,函数将初始化数据发送函数uh_ubus_data_send并准备接收POST数据。
  UH_HTTP_MSG_OPTIONS--对于OPTIONS请求,函数将发送一个空的200 OK响应,表示服务器支持跨域请求。

3.3 lua 

 lua_dispatch处理uhttpd收到的lua请求,执行lua脚本:

static struct dispatch_handler lua_dispatch = {
    .script = true,
    .check_url = check_lua_url,
    .handle_request = lua_handle_request,
};

 lua请求处理:

lua_handle_request
  create_process
    lua_main
      lua_pcall--以保护模式执行 Lua 函数调用,这意味着如果 Lua 函数中发生错误,lua_pcall会捕获错误并提供错误处理机制,而不是让错误直接导致宿主程序崩溃。

3.4 ucode

ucode_dispatch处理uhttpd收到的对ucode请求:

static struct dispatch_handler ucode_dispatch = {
    .script = true,
    .check_url = check_ucode_url,
    .handle_request = ucode_handle_request,
};

ucode请求处理:

ucode_handle_request
    create_process
        ucode_main
            uc_vm_invoke--UCode 虚拟机中用于调用函数的方法。

4 uhttpd配置文件

 参考《OpenWRT(2):uhttpd+LuCI初探

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值