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初探

<think>我们正在处理OpenWrt构建系统中的警告信息,这些警告表明在Makefile中声明的依赖项不存在。 具体问题:在`package/network/config/wifi-scripts/Makefile`中,声明了对'ucode'、'ucode-mod-nl80211'等包的依赖,但系统中找不到这些包。 解决步骤: 1. 确认依赖包是否存在:检查这些包是否在OpenWrt的包仓库中,或者是否被重命名、移除。 2. 检查拼写错误:确保Makefile中依赖的包名正确。 3. 更新或修正Makefile:如果包名已更改,则需要更新Makefile中的依赖项;如果这些包已被移除,则需要寻找替代方案或删除依赖。 4. 如果是第三方包,可能需要更新到最新版本或联系维护者。 具体分析: 根据警告,这些依赖包都是以'ucode'开头的,而'ucode'是OpenWrt中用于替换旧版Lua脚本语言的解释器。通常,这些模块应该存在于OpenWrt的包中。 可能的原因: - 这些包尚未被包含在当前配置的feed中(例如,可能位于一个未启用的feed中)。 - 这些包可能被重命名了(例如,从'ucode'改名为'ucode-full'或类似名称)。 - 当前OpenWrt版本不支持这些包(例如,版本太旧或太新)。 解决方法: 1. 检查feeds:运行`./scripts/feeds list | grep ucode`,查看是否存在这些包。 2. 更新feeds:如果feeds中没有,可以尝试更新feeds(`./scripts/feeds update -a`,然后`./scripts/feeds install -a`)。 3. 修改Makefile:如果包名已经改变,修改Makefile中的依赖项(例如,将`DEPENDS:=ucode`改为正确的包名)。 4. 如果这些包确实不存在,且没有替代品,可能需要移除这些依赖(但要注意功能是否还能正常工作)。 注意:在OpenWrt中,Makefile的依赖通常放在`DEPENDS`变量中。例如,原Makefile可能有: DEPENDS:=ucode ucode-mod-nl80211 ucode-mod-rtnl ucode-mod-ubus ucode-mod-uci 需要将这些依赖更新为当前可用的包名。 举例:在较新的OpenWrt版本中,基础ucode包名为`ucode`,而模块可能被包含在`ucode`中或单独打包。单独模块包名可能为`ucode-mod-nl80211`等,但有时也会合并。 如果确认这些包不存在,并且是必须的,可能需要添加提供这些包的feed(如来自第三方仓库)。 另外,如果这些依赖项只是运行时依赖(即`Run-time dependencies`),那么应该使用`RUN_DEPENDS`而不是`DEPENDS`(`DEPENDS`用于构建依赖)。但在这个Makefile中,可能写在了`DEPENDS`中,而实际上可能是运行时依赖。不过,OpenWrt的构建系统在编译包时也会检查运行时依赖,所以如果缺失,也会导致问题。 结论:需要根据实际情况修正Makefile中的依赖项。 </think>该警告信息源于OpenWrt构建系统中Makefile的依赖声明问题,具体分析与解决方案如下: ### 问题原因 1. **缺失的依赖包** Makefile中声明的`ucode`系列依赖项(`ucode`, `ucode-mod-nl80211`等)在当前的软件源或feeds配置中不存在,可能由于: - 包名变更(如新版改用`ucode-full`) - 包被移除或拆分 - feeds未正确更新(第三方仓库变动) 2. **依赖类型不匹配** ```makefile DEPENDS += ucode ucode-mod-nl80211 ... # 编译依赖声明 ``` 若实际应为运行时依赖,需改为: ```makefile PKG_DEPENDS += ucode ucode-mod-nl80211 ... # 运行时依赖声明 ``` ### 解决步骤 1. **验证包存在性** 终端执行: ```bash ./scripts/feeds list | grep ucode # 查看可用ucode相关包 ./scripts/feeds install ucode # 尝试安装基础包 ``` 若无输出,说明feeds未包含这些包 2. **更新feeds配置** 编辑`feeds.conf.default`,添加官方ucode源: ```conf src-git ucode https://git.openwrt.org/project/ucode.git ``` 更新源: ```bash ./scripts/feeds update -a ./scripts/feeds install ucode ``` 3. **修改Makefile依赖声明** 定位`package/network/config/wifi-scripts/Makefile`: - 方案1:修正包名(若包已重命名) ```makefile DEPENDS := @(PACKAGE_ucode) +ucode-mod-rtnl ``` - 方案2:转换为运行时依赖 ```makefile PKG_DEPENDS := ucode ucode-mod-nl80211 ... ``` 4. **选择性禁用依赖**(临时方案) 若无需ucode功能,在`make menuconfig`中: ``` Network -> WiFi-scripts -> uncheck "Enable uCode support" ``` ### 预防措施 - 定期执行`./scripts/feeds update`同步仓库 - 使用`DEPENDS:=\@(PACKAGE_xxx)`确保依赖包存在才启用 - 通过`make package/index`生成本地包索引验证依赖
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值