packages icon indicating copy to clipboard operation
packages copied to clipboard

curl add http/3 support by default

Open user8446 opened this issue 1 year ago • 86 comments

Maintainer: @stangri

Hi,

cURL OpenWrt package currently does not support HTTP/3 support but should. This protocol is now widely used everywhere, is supported in all major browsers, and has many advantages over HTTPS/2 including speed and privacy.

For example https-dns-proxy can now use HTTP/3 for DNS resolvers that use it. DNS is extremely latency sensitive in which a faster protocol would benefit it and be noticeable on pageload and responsiveness on OpenWrt connected devices.

user8446 avatar Sep 16 '22 03:09 user8446

@user8446 Thanks for bringing it up.

Looking at support for HTTP/3 in curl it is experimental and requires:

  1. patched OpenSSL library.
  2. two more 3rd party libraries: libngtcp2 and libnghttp3.

Which brings the following concerns to mind:

  1. OpenSSL is rather large and by default curl now depends on mbedtls (used to on WolfSSL, used by wpad too) due to the space constraints on most devices OpenWrt is available for.
  2. Also space concerns over two extra libraries.

So with the current state I don't think it would be accepted as a default curl build option to include support for HTTP/3.

However if you or anyone else wants to contribute the PR to enable building curl with HTTP/3 support as an option for any of the existing SSL libraries in OpenWrt, I'd gladly test it and advocate for merging said PR.

stangri avatar Sep 16 '22 04:09 stangri

Hi @stangri thanks for the reply. Not sure if it would better but there is also LibreSSL.

I don't have the knowledge to add HTTP/3 so the best I could do is donate to fund adding it.

user8446 avatar Sep 16 '22 14:09 user8446

quictls + libngtcp2 + libnghttp3, it works well

image

sbwml avatar Aug 19 '23 07:08 sbwml

@sbwml That is great! How did you build this? Was hoping openssl3 in master has quic but it doesn't:

root@OpenWrt:~# openssl version
OpenSSL 3.0.10 1 Aug 2023 (Library: OpenSSL 3.0.10 1 Aug 2023)

user8446 avatar Aug 19 '23 13:08 user8446

 -----------------------------------------------------
 OpenWrt 23.05.0-rc2, r23228-cd17d8df2a
 -----------------------------------------------------
[root@OpenWrt ~]# openssl version
OpenSSL 3.0.10+quic 1 Aug 2023 (Library: OpenSSL 3.0.10+quic 1 Aug 2023)
[root@OpenWrt ~]#
[root@OpenWrt ~]# openssl version -a
OpenSSL 3.0.10+quic 1 Aug 2023 (Library: OpenSSL 3.0.10+quic 1 Aug 2023)
built on: Mon Jun 26 11:20:39 2023 UTC
platform: linux-aarch64-openwrt
options:  bn(64,64)
compiler: aarch64-openwrt-linux-musl-gcc -fPIC -pthread -Wa,--noexecstack -Wall -O3 -Wl,--gc-sections -pipe -march=armv8-a+crc+crypto -fno-caller-saves -fno-plt -fhonour-copts -ffunction-sections -fdata-sections -Wformat -Werror=format-security -fstack-protector -D_FORTIFY_SOURCE=1 -Wl,-z,now -Wl,-z,relro -Ofast -DPIC -fPIC -pipe -march=armv8-a+crc+crypto -fno-caller-saves -fno-plt -fhonour-copts -ffunction-sections -fdata-sections -Wformat -Werror=format-security -fstack-protector -Ofast -fPIC -znow -zrelro -DOPENSSL_USE_NODELETE -DOPENSSL_PIC -DOPENSSL_BUILDING_OPENSSL -DNDEBUG -D_FORTIFY_SOURCE=1 -DPIC -DDEVRANDOM="\"/dev/hwrng\""
OPENSSLDIR: "/etc/ssl"
ENGINESDIR: "/usr/lib/engines-3"
MODULESDIR: "/usr/lib/ossl-modules"
Seeding source: os-specific
CPUINFO: OPENSSL_armcap=0x3d
[root@OpenWrt ~]#

sbwml avatar Aug 19 '23 14:08 sbwml

Because I built OpenWrt for myself, I don't need to follow the code specifications. I replaced openssl pkg with the quitls source.

sbwml avatar Aug 19 '23 14:08 sbwml

Thank you for sharing!

user8446 avatar Aug 19 '23 14:08 user8446

If you're willing to break the OpenWrt source code, you can do it.

# get openwrt source
git clone https://github.com/openwrt/openwrt --depth=1 -b v23.05.0-rc2
cd openwrt
./scripts/feeds update -a
./scripts/feeds install -a

# openssl -> quictls
rm -rf package/libs/openssl
git clone https://github.com/sbwml/package_libs_openssl package/libs/openssl

# nghttp3
git clone https://github.com/sbwml/package_libs_nghttp3 package/libs/nghttp3

# ngtcp2
git clone https://github.com/sbwml/package_libs_ngtcp2 package/libs/ngtcp2

# curl - http3/quic
rm -rf feeds/packages/net/curl
git clone https://github.com/sbwml/feeds_packages_net_curl feeds/packages/net/curl

Add this to .config

CONFIG_PACKAGE_curl=y
CONFIG_PACKAGE_libcurl=y
CONFIG_LIBCURL_NGHTTP3=y
CONFIG_LIBCURL_NGTCP2=y
CONFIG_LIBCURL_OPENSSL=y
# CONFIG_LIBCURL_GNUTLS is not set
# CONFIG_LIBCURL_MBEDTLS is not set
# CONFIG_LIBCURL_NOSSL is not set
# CONFIG_LIBCURL_WOLFSSL is not set

At this point, you can build a curl that supports h3/quic.

sbwml avatar Aug 19 '23 14:08 sbwml

I haven't done this before but I will research. Thank you for the info!

user8446 avatar Aug 19 '23 15:08 user8446

If you're willing to break the OpenWrt source code, you can do it.

@sbwml Would you consider sending PRs for existing openssl and curl packages and the new libnghttp3 and libngtcp2 packages?

stangri avatar Aug 19 '23 15:08 stangri

If you're willing to break the OpenWrt source code, you can do it.

@sbwml Would you consider sending PRs for existing openssl and curl packages and the new libnghttp3 and libngtcp2 packages?

😛 It's too difficult for me, I don't know English and I'm not familiar with using git, these are the biggest obstacles

-- Translated from Youdao

sbwml avatar Aug 19 '23 16:08 sbwml

@sbwml thanks for your prompt reply. Would you be OK with me submitting PRs crediting you for the code/testing?

stangri avatar Aug 19 '23 17:08 stangri

@sbwml thanks for your prompt reply. Would you be OK with me submitting PRs crediting you for the code/testing?

Sure 👍

sbwml avatar Aug 19 '23 17:08 sbwml

Thank you @stangri for looking into it, http3 will definitely be a benefit with DNS being so sensitive to latency

user8446 avatar Aug 19 '23 19:08 user8446

Sorry, just noticed this uses a fork of OpenSSL, I'm pretty sure this will not be accepted to replace the official OpenSSL in OpenWrt. I'll try to reach to maintainer to see if this can be added as a variant.

stangri avatar Aug 21 '23 01:08 stangri

@sbwml have you tested/made updates to work with 23.05.0-rc3 and curl 8.3.0?

stangri avatar Sep 25 '23 22:09 stangri

@sbwml have you tested/made updates to work with 23.05.0-rc3 and curl 8.3.0?

I am currently using OpenWrt-23.05-rc3 and curl/8.2.1.

  _______                     ________        __
 |       |.-----.-----.-----.|  |  |  |.----.|  |_
 |   -   ||  _  |  -__|     ||  |  |  ||   _||   _|
 |_______||   __|_____|__|__||________||__|  |____|
          |__| W I R E L E S S   F R E E D O M
 -----------------------------------------------------
 OpenWrt 23.05.0-rc3, r23389-5deed175a5
 -----------------------------------------------------
[root@OpenWrt ~]# curl --version
curl 8.2.1 (aarch64-openwrt-linux-gnu) libcurl/8.2.1 OpenSSL/3.0.10 nghttp2/1.51.0 ngtcp2/0.18.0 nghttp3/0.14.0
Release-Date: 2023-07-26
Protocols: file ftp ftps http https mqtt
Features: alt-svc HSTS HTTP2 HTTP3 HTTPS-proxy IPv6 Largefile SSL threadsafe UnixSockets
[root@OpenWrt ~]#

sbwml avatar Sep 26 '23 02:09 sbwml

https://x86.cooluc.com/minimal/openwrt-23.05/v23.05.0-rc3/manifest.txt?preview

sbwml avatar Sep 26 '23 02:09 sbwml

@sbwml following your instructions I get the error on building curl with ngtcp2 with 23.05.0-rc3. Any idea on how to overcome this?

checking for nghttp2_session_get_stream_local_window_size in -lnghttp2... yes
checking for nghttp2/nghttp2.h... yes
configure: Added /home/stangri/development/Builder/openwrt/staging_dir/target-x86_64_musl/usr/lib to CURL_LIBRARY_PATH
checking for libngtcp2 options with pkg-config... found
configure: -l is -lngtcp2
configure: -I is -I/home/stangri/development/Builder/openwrt/staging_dir/target-x86_64_musl/usr/include
configure: -L is -L/home/stangri/development/Builder/openwrt/staging_dir/target-x86_64_musl/usr/lib
checking for ngtcp2_conn_client_new_versioned in -lngtcp2... yes
checking for ngtcp2/ngtcp2.h... yes
configure: Added  to CURL_LIBRARY_PATH
checking for libngtcp2_crypto_quictls options with pkg-config... no
configure: error: --with-ngtcp2 was specified but could not find ngtcp2_crypto_quictls pkg-config file.
make[3]: *** [Makefile:192: /home/stangri/development/Builder/openwrt/build_dir/target-x86_64_musl/curl-8.2.1/.configured_73e8a40fec0d702ff96a3dc5ec6098da] Error 1
make[3]: Leaving directory '/home/stangri/development/Builder/openwrt/feeds/packages/net/curl'
time: package/feeds/packages/curl/compile#41.67#1.51#43.63
    ERROR: package/feeds/packages/curl failed to build.
make[2]: *** [package/Makefile:120: package/feeds/packages/curl/compile] Error 1
make[2]: Leaving directory '/home/stangri/development/Builder/openwrt'
make[1]: *** [package/Makefile:114: /home/stangri/development/Builder/openwrt/staging_dir/target-x86_64_musl/stamp/.package_compile] Error 2
make[1]: Leaving directory '/home/stangri/development/Builder/openwrt'
make: *** [/home/stangri/development/Builder/openwrt/include/toplevel.mk:232: world] Error 2

stangri avatar Sep 26 '23 03:09 stangri

configure: error: --with-ngtcp2 was specified but could not find ngtcp2_crypto_quictls pkg-config file.

ngtcp2 also needs to be based on quicssl header files and libraries. It cannot be built directly in the original openwrt source code because it requires https://github.com/quictls/openssl .

I was able to build it because of tampering with openwrt's openssl package. https://github.com/sbwml/package_libs_openssl

sbwml avatar Sep 26 '23 03:09 sbwml

There are also examples of using quickls from the ngtcp2 readme file. https://github.com/ngtcp2/ngtcp2#build-from-git

sbwml avatar Sep 26 '23 03:09 sbwml

configure: error: --with-ngtcp2 was specified but could not find ngtcp2_crypto_quictls pkg-config file.

ngtcp2 also needs to be based on quicssl header files and libraries. It cannot be built directly in the original openwrt source code because it requires https://github.com/quictls/openssl .

I was able to build it because of tampering with openwrt's openssl package. https://github.com/sbwml/package_libs_openssl

Yes, I was using libs/curl from your repo as per your comment above: https://github.com/openwrt/packages/issues/19382#issuecomment-1685022455. I'm still getting an error when building. I wonder if there are steps you've left out in the instructions.

stangri avatar Sep 26 '23 09:09 stangri

Yes, I was using libs/curl from your repo as per your comment above: #19382 (comment). I'm still getting an error when building. I wonder if there are steps you've left out in the instructions.

Nothing was missing. from your error logs, it doesn't seem to use quictls when compiling ngtcp2, because it can't find libngtcp2_crypto_quictls.pc. I guess the source code of your build package is not cloned from https://github.com/openwrt/openwrt

It's more like using the OpenWrt sdk.

sbwml avatar Sep 26 '23 10:09 sbwml

If you use openwrt sdk to test compile it, you should replace openssl from feeds.

rm -rf feeds/base/package/libs/openssl
git clone https://github.com/sbwml/package_libs_openssl feeds/base/package/libs/openssl

sbwml avatar Sep 26 '23 10:09 sbwml

The ~~only~~ EDIT: patched curl and quictls are custom package needed now i.e.

# openssl -> quictls
rm -rf package/libs/openssl
git clone https://github.com/sbwml/package_libs_openssl package/libs/openssl

# curl - http3/quic
rm -rf feeds/packages/net/curl
git clone https://github.com/sbwml/feeds_packages_net_curl feeds/packages/net/curl

Unfortunately the default settings don't allow it to build. If you use git checkout dev and edit the Makefile you can successfully build openssl/quictls:

PKG_NAME:=openssl

PKG_VERSION:=3.0.12
PKG_RELEASE:=1
PKG_BUILD_FLAGS:=no-mips16 gc-sections no-lto

PKG_BUILD_PARALLEL:=1

PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://github.com/sbwml/openssl.git
PKG_SOURCE_VERSION:=9e001c32f3b0a22ce9968ef27850c30e8a8e3ee1
PKG_MIRROR_HASH:=f93c9e8edde5e9166119de31755fc87b4aa34863662f67ddfcba14d0b6b69b61

Leaving at default branch and changing out the quictls package source url to the official versions possibly works but I haven't tried. It's easy enough to get the sha256 hashes for each available release though.

abelian424 avatar Dec 16 '23 07:12 abelian424

The ~only~ EDIT: patched curl and quictls are custom package needed now i.e.

I am currently patching the openssl package of openwrt to implement quic support. https://github.com/sbwml/r4s_build_script/tree/master/openwrt/patch/openssl/quic

Also I cannot directly use nghttp3 and ngtcp2 provided by openwrt feeds.

https://github.com/sbwml/r4s_build_script/blob/master/openwrt/scripts/00-prepare_base.sh#L206 https://github.com/sbwml/r4s_build_script/blob/master/openwrt/scripts/00-prepare_base.sh#L210

  _______                     ________        __
 |       |.-----.-----.-----.|  |  |  |.----.|  |_
 |   -   ||  _  |  -__|     ||  |  |  ||   _||   _|
 |_______||   __|_____|__|__||________||__|  |____|
          |__| W I R E L E S S   F R E E D O M
 -----------------------------------------------------
 OpenWrt 23.05.2, r23630-842932a63d
 -----------------------------------------------------
[root@OpenWrt ~]# 
[root@OpenWrt ~]# openssl version -a
OpenSSL 3.0.12+quic 24 Oct 2023 (Library: OpenSSL 3.0.12+quic 24 Oct 2023)
built on: Tue Nov 14 13:38:11 2023 UTC
platform: linux-aarch64-openwrt
options:  bn(64,64)
compiler: aarch64-openwrt-linux-musl-gcc -fPIC -pthread -Wa,--noexecstack -Wall -O3 -Wl,--gc-sections -pipe -march=armv8-a+crc+crypto -fno-caller-saves -fno-plt -fhonour-copts -ffunction-sections -fdata-sections -Wformat -Werror=format-security -fstack-protector -D_FORTIFY_SOURCE=1 -Wl,-z,now -Wl,-z,relro -Ofast -DPIC -fPIC -pipe -march=armv8-a+crc+crypto -fno-caller-saves -fno-plt -fhonour-copts -ffunction-sections -fdata-sections -Wformat -Werror=format-security -fstack-protector -Ofast -fPIC -znow -zrelro -DOPENSSL_USE_NODELETE -DOPENSSL_PIC -DOPENSSL_BUILDING_OPENSSL -DNDEBUG -D_FORTIFY_SOURCE=1 -DPIC -DDEVRANDOM="\"/dev/hwrng\""
OPENSSLDIR: "/etc/ssl"
ENGINESDIR: "/usr/lib/engines-3"
MODULESDIR: "/usr/lib/ossl-modules"
Seeding source: os-specific
CPUINFO: OPENSSL_armcap=0x3d
[root@OpenWrt ~]# 
[root@OpenWrt ~]# curl --version
curl 8.5.0 (aarch64-openwrt-linux-gnu) libcurl/8.5.0 quictls/3.0.12 nghttp2/1.57.0 ngtcp2/1.1.0 nghttp3/1.1.0
Release-Date: 2023-12-06
Protocols: file ftp ftps http https mqtt
Features: alt-svc HSTS HTTP2 HTTP3 HTTPS-proxy IPv6 Largefile SSL threadsafe UnixSockets
[root@OpenWrt ~]# 
[root@OpenWrt ~]# curl -I --http3-only https://tls.cooluc.com
HTTP/3 200 
server: nginx/1.25.3 (Red Hat Enterprise Linux release 9.2 (Plow))
date: Sat, 16 Dec 2023 10:11:25 GMT
content-type: text/html; charset=utf-8
content-length: 5633
last-modified: Fri, 16 Dec 2022 21:22:34 GMT
vary: accept-encoding
etag: "639ce19a-1601"
alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
x-quic: h3
x-xss-protection: 1
x-xss-protection: mod=block
strict-transport-security: max-age=63072000
public-key-pins: pin-sha256="BbrVIhEYvvBL6FiyC7nzVKLLDU3GPYdqHWAfk0ev/80="; pin-sha256="amMeV6gb9QNx0Zf7FtJ19Wa/t2B7KpCF/1n2Js3UuSU="; max-age=31536000; includeSubDomains
accept-ranges: bytes

[root@OpenWrt ~]#

sbwml avatar Dec 16 '23 10:12 sbwml

Also I cannot directly use nghttp3 and ngtcp2 provided by openwrt feeds.

Why? Have you looked into patching the sources from openwrt feeds?

stangri avatar Dec 16 '23 15:12 stangri

Also I cannot directly use nghttp3 and ngtcp2 provided by openwrt feeds.

Why? Have you looked into patching the sources from openwrt feeds?

因为 cmake

sbwml avatar Dec 16 '23 16:12 sbwml

The ~only~ EDIT: patched curl and quictls are custom package needed now i.e.

I am currently patching the openssl package of openwrt to implement quic support. https://github.com/sbwml/r4s_build_script/tree/master/openwrt/patch/openssl/quic

Also I cannot directly use nghttp3 and ngtcp2 provided by openwrt feeds.

https://github.com/sbwml/r4s_build_script/blob/master/openwrt/scripts/00-prepare_base.sh#L206 https://github.com/sbwml/r4s_build_script/blob/master/openwrt/scripts/00-prepare_base.sh#L210

I find only superficial differences between curl, nghttp3, and ngtcp2:

https://github.com/sbwml/feeds_packages_net_curl/blob/main/Config.in https://github.com/openwrt/packages/blob/master/net/curl/Config.in

https://github.com/sbwml/package_libs_nghttp3/blob/main/Makefile https://github.com/openwrt/packages/blob/master/libs/nghttp3/Makefile

https://github.com/sbwml/package_libs_ngtcp2/blob/main/Makefile https://github.com/openwrt/packages/blob/master/libs/ngtcp2/Makefile

It is a case of OpenWrt catching up to your packages (and in the case of curl, outpacing by being 8.5.0 instead of 8.4.0)?

Also I cannot directly use nghttp3 and ngtcp2 provided by openwrt feeds.

Why? Have you looked into patching the sources from openwrt feeds?

因为 cmake

What is due to cmake?

I can just edit this file to download quictls:

PKG_BASE:=$(subst $(space),.,$(wordlist 1,2,$(subst .,$(space),$(PKG_VERSION))))
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-quic1.tar.gz
PKG_SOURCE_URL:= \
        https://github.com/quictls/openssl/archive/refs/tags/

PKG_HASH:=ca0e148f5e50c38198a25559d52cc06781345f5bff15de526ff65b0cc623d1bc

and then use this patch by @sbwml to eliminate intentional versioning differences from the quictls team:

--- a/VERSION.dat
+++ b/VERSION.dat
@@ -4,4 +4,4 @@ PATCH=10
 PRE_RELEASE_TAG=
 RELEASE_DATE="1 Aug 2023"
-SHLIB_VERSION=81.3
+SHLIB_VERSION=3

I'm going to try to compile without this patch but with all these patches and see what happens.

abelian424 avatar Dec 17 '23 10:12 abelian424

It is a case of OpenWrt catching up to your packages (and in the case of curl, outpacing by being 8.5.0 instead of 8.4.0)?

curl 的版本不是重点,我在GitHub Action 为自己构建 openwrt 固件时始终取自 openwrt/packages main 分支的 curl,它的版本是 8.5.0

What is due to cmake?

在编译 curl 并启用 ngtcp2 库支持时,使用 cmake 编译 ngtcp2 & nghttp3,那么 curl 将会编译失败(我没有保留任何日志,因为已经过去三个月了,你可以自己试试),我第一次让 curl 支持 http3 时就是使用的 cmake 去编译 ngtcp2 & nghttp3 ,但是当时 curl 编译失败了,最后我使用默认的 automake 编译成功了。毕竟我的需求只是让 curl 实现 quic/http3 的支持,而不是使用什么方式去编译它,所以并没有进一步的去了解原因。

PS:来自手机的回复,没有任何方式将其翻译成英文

sbwml avatar Dec 17 '23 11:12 sbwml