mirror of
https://github.com/lwthiker/curl-impersonate.git
synced 2026-10-10 11:26:33 +00:00
Firefox impersonation was not updated in a long while. Add impersonation for Firefox 109. The TLS signature is identical to previous versions, with the usual changes to the HTTP headers. Update NSS to the latest version as well, even though it is not strictly necessary for the impersonation.
437 lines
15 KiB
Makefile
437 lines
15 KiB
Makefile
# Makefile to build curl-impersonate
|
|
# Some Makefile tricks were taken from https://tech.davis-hansson.com/p/make/
|
|
|
|
SHELL := bash
|
|
.ONESHELL:
|
|
.SHELLFLAGS := -euc
|
|
.DELETE_ON_ERROR:
|
|
# MAKEFLAGS += --warn-undefined-variables
|
|
# MAKEFLAGS += --no-builtin-rules
|
|
|
|
BROTLI_VERSION := 1.0.9
|
|
# In case this is changed, update build-and-test-make.yml as well
|
|
NSS_VERSION := nss-3.87
|
|
NSS_URL := https://ftp.mozilla.org/pub/security/nss/releases/NSS_3_87_RTM/src/nss-3.87-with-nspr-4.35.tar.gz
|
|
# In case this is changed, update build-and-test-make.yml as well
|
|
BORING_SSL_COMMIT := 3a667d10e94186fd503966f5638e134fe9fb4080
|
|
NGHTTP2_VERSION := nghttp2-1.46.0
|
|
NGHTTP2_URL := https://github.com/nghttp2/nghttp2/releases/download/v1.46.0/nghttp2-1.46.0.tar.bz2
|
|
CURL_VERSION := curl-7.84.0
|
|
|
|
brotli_install_dir := $(abspath brotli-$(BROTLI_VERSION)/out/installed)
|
|
brotli_static_libs := $(brotli_install_dir)/lib/libbrotlicommon-static.a $(brotli_install_dir)/lib/libbrotlidec-static.a
|
|
nss_install_dir := $(abspath $(NSS_VERSION)/dist/Release)
|
|
nss_static_libs := $(nss_install_dir)/lib/libnss_static.a
|
|
boringssl_install_dir := $(abspath boringssl/build)
|
|
boringssl_static_libs := $(boringssl_install_dir)/lib/libssl.a $(boringssl_install_dir)/lib/libcrypto.a
|
|
nghttp2_install_dir := $(abspath $(NGHTTP2_VERSION)/installed)
|
|
nghttp2_static_libs := $(nghttp2_install_dir)/lib/libnghttp2.a
|
|
|
|
# Dependencies needed to compile the Firefox version
|
|
firefox_libs := $(brotli_static_libs) $(nss_static_libs) $(nghttp2_static_libs)
|
|
# Dependencies needed to compile the Chrome version
|
|
chrome_libs := $(brotli_static_libs) $(boringssl_static_libs) $(nghttp2_static_libs)
|
|
|
|
# The following variables will be set by the configure script.
|
|
prefix = @prefix@
|
|
exec_prefix = @exec_prefix@
|
|
srcdir = @abs_srcdir@
|
|
host = @host@
|
|
host_alias = @host_alias@
|
|
host_cpu = @host_cpu@
|
|
host_os = @host_os@
|
|
build = @build@
|
|
# Whether to link curl-impersonate with libcurl-impersonate statically.
|
|
static_build = @static_build@
|
|
# Whether the user provided a specific find for zlib
|
|
with_zlib = @with_zlib@
|
|
# Path to be passed to curl's --with-ca-bundle configure option.
|
|
with_ca_bundle = @with_ca_bundle@
|
|
# Path to be passed to curl's --with-ca-path configure option.
|
|
with_ca_path = @with_ca_path@
|
|
# Path to be passed to curl's --with-libnssckbi configure option (an option
|
|
# added for curl-impersonate).
|
|
with_libnssckbi = @with_libnssckbi@
|
|
|
|
CC = @CC@
|
|
CXX = @CXX@
|
|
STRIP = @STRIP@
|
|
|
|
# Auto-generate Makefile help.
|
|
# Borrowed from https://marmelab.com/blog/2016/02/29/auto-documented-makefile.html
|
|
help: ## Show this help message
|
|
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
|
|
.PHONY: help
|
|
.DEFAULT_GOAL := help
|
|
|
|
firefox-build: $(CURL_VERSION)/.firefox ## Build the Firefox version of curl-impersonate
|
|
cd $(CURL_VERSION)
|
|
# Don't pass this Makefile's MAKEFLAGS
|
|
$(MAKE) MAKEFLAGS=
|
|
.PHONY: firefox-build
|
|
|
|
firefox-checkbuild: ## Run basic checks on the built binary
|
|
ifeq ($(host),$(build))
|
|
cd $(CURL_VERSION)
|
|
# Make sure all needed features were compiled in
|
|
./src/curl-impersonate-ff -V | grep -q zlib
|
|
./src/curl-impersonate-ff -V | grep -q brotli
|
|
./src/curl-impersonate-ff -V | grep -q nghttp2
|
|
./src/curl-impersonate-ff -V | grep -q NSS
|
|
$(info Build OK)
|
|
else
|
|
$(info Cross compiling, skipping checkbuild)
|
|
endif
|
|
.PHONY: firefox-checkbuild
|
|
|
|
firefox-install: ## Install the Firefox version of curl-impersonate after build
|
|
cd $(CURL_VERSION)
|
|
$(MAKE) install-exec MAKEFLAGS=
|
|
# Wrapper scripts for the Firefox version (e.g. 'curl_ff98')
|
|
install $(srcdir)/firefox/curl_ff* @bindir@
|
|
.PHONY: firefox-install
|
|
|
|
firefox-install-strip: ## Like 'firefox-install', but strip binaries for smaller size
|
|
cd $(CURL_VERSION)
|
|
$(MAKE) install-exec MAKEFLAGS=
|
|
# We could have used 'install-strip' but then the docs would be installed as well.
|
|
# Instead strip manually.
|
|
$(STRIP) @bindir@/curl-impersonate-ff
|
|
# Wrapper scripts for the Firefox version (e.g. 'curl_ff98')
|
|
install $(srcdir)/firefox/curl_ff* @bindir@
|
|
.PHONY: firefox-install-strip
|
|
|
|
firefox-uninstall: ## Uninstall the Firefox version of curl-impersonate after 'make install'
|
|
cd $(CURL_VERSION)
|
|
$(MAKE) uninstall MAKEFLAGS=
|
|
rm -Rf @bindir@/curl_ff*
|
|
.PHONY: firefox-uninstall
|
|
|
|
firefox-clean: ## Clean build artifacts of the Firefox version. Use after re-running './configure'
|
|
cd $(CURL_VERSION)
|
|
$(MAKE) clean MAKEFLAGS=
|
|
rm -f .firefox
|
|
.PHONY: firefox-clean
|
|
|
|
chrome-build: $(CURL_VERSION)/.chrome ## Build the Chrome version of curl-impersonate
|
|
cd $(CURL_VERSION)
|
|
# Don't pass this Makefile's MAKEFLAGS
|
|
$(MAKE) MAKEFLAGS=
|
|
.PHONY: chrome-build
|
|
|
|
chrome-checkbuild: ## Run basic checks on the built binary
|
|
ifeq ($(host),$(build))
|
|
cd $(CURL_VERSION)
|
|
# Make sure all needed features were compiled in
|
|
./src/curl-impersonate-chrome -V | grep -q zlib
|
|
./src/curl-impersonate-chrome -V | grep -q brotli
|
|
./src/curl-impersonate-chrome -V | grep -q nghttp2
|
|
./src/curl-impersonate-chrome -V | grep -q BoringSSL
|
|
$(info Build OK)
|
|
else
|
|
$(info Cross compiling, skipping checkbuild)
|
|
endif
|
|
.PHONY: chrome-checkbuild
|
|
|
|
chrome-install: ## Install the Chrome version of curl-impersonate after build
|
|
cd $(CURL_VERSION)
|
|
$(MAKE) install-exec MAKEFLAGS=
|
|
# Wrapper scripts for the Chrome version (e.g. 'curl_chrome99')
|
|
install $(srcdir)/chrome/curl_chrome* $(srcdir)/chrome/curl_edge* $(srcdir)/chrome/curl_safari* @bindir@
|
|
.PHONY: chrome-install
|
|
|
|
chrome-install-strip: ## Like 'chrome-install', but strip binaries for smaller size
|
|
cd $(CURL_VERSION)
|
|
$(MAKE) install-exec MAKEFLAGS=
|
|
# We could have used 'install-strip' but then the docs would be installed as well.
|
|
# Instead strip manually.
|
|
$(STRIP) @bindir@/curl-impersonate-chrome
|
|
# Wrapper scripts for the Chrome version (e.g. 'curl_chrome99')
|
|
install $(srcdir)/chrome/curl_chrome* $(srcdir)/chrome/curl_edge* $(srcdir)/chrome/curl_safari* @bindir@
|
|
.PHONY: chrome-install-strip
|
|
|
|
chrome-uninstall: ## Uninstall the Chrome version of curl-impersonate after 'make install'
|
|
cd $(CURL_VERSION)
|
|
$(MAKE) uninstall MAKEFLAGS=
|
|
rm -Rf @bindir@/curl_chrome* @bindir@/curl_edge* @bindir@/curl_safari*
|
|
.PHONY: chrome-uninstall
|
|
|
|
chrome-clean: ## Clean build artifacts of the Chrome version. Use after re-running './configure'
|
|
cd $(CURL_VERSION)
|
|
$(MAKE) clean MAKEFLAGS=
|
|
rm -f .chrome
|
|
.PHONY: chrome-clean
|
|
|
|
clean: ## Remove all build artifacts, including dependencies
|
|
rm -Rf brotli-$(BROTLI_VERSION).tar.gz brotli-$(BROTLI_VERSION)
|
|
rm -Rf $(NSS_VERSION).tar.gz $(NSS_VERSION)
|
|
rm -Rf boringssl.zip boringssl
|
|
rm -Rf $(NGHTTP2_VERSION).tar.bz2 $(NGHTTP2_VERSION)
|
|
rm -Rf $(CURL_VERSION).tar.xz $(CURL_VERSION)
|
|
|
|
brotli-$(BROTLI_VERSION).tar.gz:
|
|
curl -L "https://github.com/google/brotli/archive/refs/tags/v${BROTLI_VERSION}.tar.gz" \
|
|
-o "brotli-${BROTLI_VERSION}.tar.gz"
|
|
|
|
$(brotli_static_libs): brotli-$(BROTLI_VERSION).tar.gz
|
|
tar xf brotli-$(BROTLI_VERSION).tar.gz
|
|
cd brotli-$(BROTLI_VERSION)
|
|
mkdir -p out
|
|
cd out
|
|
|
|
# Convert autoconf style os name to CMake style os name.
|
|
case $(host_os) in \
|
|
linux*) \
|
|
system_name=Linux \
|
|
;; \
|
|
darwin*) \
|
|
system_name=Darwin \
|
|
;; \
|
|
*) \
|
|
system_name=$(host_os) \
|
|
;; \
|
|
esac
|
|
|
|
@cmake@ -DCMAKE_BUILD_TYPE=Release \
|
|
-DCMAKE_INSTALL_PREFIX=./installed \
|
|
-DCMAKE_INSTALL_LIBDIR=lib \
|
|
-DCMAKE_CXX_COMPILER=$(CXX) \
|
|
-DCMAKE_C_COMPILER=$(CC) \
|
|
-DCMAKE_SYSTEM_NAME=$$system_name \
|
|
-DCMAKE_SYSTEM_PROCESSOR=$(host_cpu) \
|
|
..
|
|
|
|
@cmake@ --build . --config Release --target install
|
|
|
|
|
|
$(NSS_VERSION).tar.gz:
|
|
curl -L -o $(NSS_VERSION).tar.gz $(NSS_URL)
|
|
|
|
$(nss_static_libs): $(NSS_VERSION).tar.gz
|
|
tar xf $(NSS_VERSION).tar.gz
|
|
|
|
ifeq ($(host),$(build))
|
|
# Native build, use NSS' build script.
|
|
cd $(NSS_VERSION)/nss
|
|
./build.sh -o --disable-tests --static --python=python3
|
|
else
|
|
# We are cross compiling.
|
|
# Cross compiling NSS is not supported by its build script and is poorly
|
|
# documented. We need to compile NSPR manually and only then compile nss.
|
|
case $(host_cpu) in \
|
|
*64*) \
|
|
use_64="1"; \
|
|
nspr_configure_flags="--enable-64bit"; \
|
|
;; \
|
|
*) \
|
|
use_64="0"; \
|
|
;; \
|
|
esac
|
|
|
|
# Cross-compile nspr separately
|
|
cd $(NSS_VERSION)/nspr
|
|
./configure --prefix=$(nss_install_dir) \
|
|
--disable-debug --enable-optimize \
|
|
--target=$(host_alias) \
|
|
$$nspr_configure_flags
|
|
$(MAKE) MAKEFLAGS=
|
|
$(MAKE) install MAKEFLAGS=
|
|
|
|
# Now we can run ./build.sh with the already built nspr
|
|
cd ../nss
|
|
CC=$(CC) CXX=$(CXX) CCC=$(CXX) \
|
|
./build.sh -o --disable-tests --static --python=python3 \
|
|
--with-nspr=$(nss_install_dir)/include/nspr:$(nss_install_dir)/lib \
|
|
--target=$(host_cpu) \
|
|
-Duse_system_zlib=0 \
|
|
-Dsign_libs=0
|
|
endif
|
|
# Hack for macOS: Remove dynamic libraries to force the linker to use the
|
|
# static ones when linking curl.
|
|
rm -Rf $(nss_install_dir)/lib/*.dylib
|
|
|
|
|
|
boringssl.zip:
|
|
curl -L https://github.com/google/boringssl/archive/$(BORING_SSL_COMMIT).zip \
|
|
-o boringssl.zip
|
|
|
|
# Patch boringssl and use a dummy '.patched' file to mark it patched
|
|
boringssl/.patched: $(srcdir)/chrome/patches/boringssl-*.patch
|
|
unzip -q -o boringssl.zip
|
|
mv boringssl-$(BORING_SSL_COMMIT) boringssl
|
|
cd boringssl/
|
|
for p in $^; do patch -p1 < $$p; done
|
|
touch .patched
|
|
|
|
$(boringssl_static_libs): boringssl.zip boringssl/.patched
|
|
mkdir -p $(boringssl_install_dir)
|
|
cd $(boringssl_install_dir)
|
|
|
|
# Convert autoconf style os name to CMake style os name.
|
|
case $(host_os) in \
|
|
linux*) \
|
|
system_name=Linux \
|
|
;; \
|
|
darwin*) \
|
|
system_name=Darwin \
|
|
;; \
|
|
*) \
|
|
system_name=Linux \
|
|
;; \
|
|
esac
|
|
|
|
# The extra CMAKE_C_FLAGS are needed because otherwise boringssl fails to
|
|
# compile in release mode on some systems with gcc 12 (e.g. Fedora).
|
|
# In addition, guard these options with -Wno-unknown-warning-option to
|
|
# prevent clang from failing on them.
|
|
@cmake@ -DCMAKE_BUILD_TYPE=Release \
|
|
-DCMAKE_POSITION_INDEPENDENT_CODE=on \
|
|
-DCMAKE_C_FLAGS="-Wno-unknown-warning-option -Wno-stringop-overflow -Wno-array-bounds" \
|
|
-DCMAKE_CXX_COMPILER=$(CXX) \
|
|
-DCMAKE_C_COMPILER=$(CC) \
|
|
-DCMAKE_SYSTEM_NAME=$$system_name \
|
|
-DCMAKE_SYSTEM_PROCESSOR=$(host_cpu) \
|
|
-GNinja \
|
|
..
|
|
@ninja@
|
|
# Fix the directory structure so that curl can compile against it.
|
|
# See https://everything.curl.dev/source/build/tls/boringssl
|
|
mkdir -p lib
|
|
ln -sf ../crypto/libcrypto.a lib/libcrypto.a
|
|
ln -sf ../ssl/libssl.a lib/libssl.a
|
|
cp -Rf ../include .
|
|
|
|
|
|
$(NGHTTP2_VERSION).tar.bz2:
|
|
curl -L $(NGHTTP2_URL) -o $(NGHTTP2_VERSION).tar.bz2
|
|
|
|
$(nghttp2_static_libs): $(NGHTTP2_VERSION).tar.bz2
|
|
tar -xf $(NGHTTP2_VERSION).tar.bz2
|
|
cd $(NGHTTP2_VERSION)
|
|
|
|
# Set up the configure flags to nghttp2.
|
|
# If the user provided the --host flag to our configure script
|
|
# (for cross compilation), then pass it on to nghttp2.
|
|
{ \
|
|
config_flags="--prefix=$(nghttp2_install_dir)"; \
|
|
config_flags="$$config_flags --with-pic --enable-lib-only"; \
|
|
config_flags="$$config_flags --disable-shared --disable-python-bindings"; \
|
|
if test -n "$(host_alias)"; then \
|
|
config_flags="$$config_flags --host=$(host_alias)"; \
|
|
fi; \
|
|
}
|
|
|
|
./configure $$config_flags
|
|
$(MAKE) MAKEFLAGS=
|
|
$(MAKE) install MAKEFLAGS=
|
|
|
|
$(CURL_VERSION).tar.xz:
|
|
curl -L "https://curl.se/download/$(CURL_VERSION).tar.xz" \
|
|
-o "$(CURL_VERSION).tar.xz"
|
|
|
|
# Apply the "Firefox version" patches and mark using a dummy file
|
|
$(CURL_VERSION)/.patched-ff: $(srcdir)/firefox/patches/curl-*.patch
|
|
rm -Rf $(CURL_VERSION)
|
|
tar -xf $(CURL_VERSION).tar.xz
|
|
cd $(CURL_VERSION)
|
|
for p in $^; do patch -p1 < $$p; done
|
|
# Re-generate the configure script
|
|
autoreconf -fi
|
|
touch .patched-ff
|
|
rm -f .patched-chrome
|
|
|
|
# Apply the "Chorme version" patches and mark using a dummy file
|
|
$(CURL_VERSION)/.patched-chrome: $(srcdir)/chrome/patches/curl-*.patch
|
|
rm -Rf $(CURL_VERSION)
|
|
tar -xf $(CURL_VERSION).tar.xz
|
|
cd $(CURL_VERSION)
|
|
for p in $^; do patch -p1 < $$p; done
|
|
# Re-generate the configure script
|
|
autoreconf -fi
|
|
touch .patched-chrome
|
|
rm -f .patched-ff
|
|
|
|
# This is a small hack that flags that curl was patched and configured in the "firefox" version
|
|
$(CURL_VERSION)/.firefox: $(firefox_libs) $(CURL_VERSION).tar.xz $(CURL_VERSION)/.patched-ff
|
|
cd $(CURL_VERSION)
|
|
|
|
# Set up the configure flags to curl.
|
|
# If the user provided the --host flag to our configure script
|
|
# (for cross compilation), then pass it on to curl.
|
|
{ \
|
|
config_flags="--prefix=@prefix@"; \
|
|
config_flags+=" --with-nghttp2=$(nghttp2_install_dir)"; \
|
|
config_flags+=" --with-brotli=$(brotli_install_dir)"; \
|
|
config_flags+=" --with-nss=$(nss_install_dir) --with-nss-deprecated"; \
|
|
config_flags+=" USE_CURL_SSLKEYLOGFILE=true"; \
|
|
if test "$(static_build)" = "yes"; then \
|
|
config_flags+=" --enable-static --disable-shared"; \
|
|
fi; \
|
|
if test -n "$(host_alias)"; then \
|
|
config_flags+=" --host=$(host_alias)"; \
|
|
fi; \
|
|
if test -n "$(with_zlib)"; then \
|
|
config_flags+=" --with-zlib=$(with_zlib)"; \
|
|
else \
|
|
config_flags+=" --with-zlib"; \
|
|
fi; \
|
|
if test -n "$(with_libnssckbi)"; then \
|
|
config_flags+=" --with-libnssckbi=$(with_libnssckbi)"; \
|
|
fi; \
|
|
add_cflags="-I$(nss_install_dir)/../public/nss"; \
|
|
add_cflags+=" -I$(nss_install_dir)/include/nspr"; \
|
|
}
|
|
|
|
echo "Configuring curl with: $$config_flags"
|
|
|
|
./configure $$config_flags CFLAGS="$$add_cflags"
|
|
# Remove possible leftovers from a previous compilation
|
|
$(MAKE) clean MAKEFLAGS=
|
|
touch .firefox
|
|
# Remove the Chrome flag if it exists
|
|
rm -f .chrome
|
|
|
|
# This is a small hack that flags that curl was patched and configured in the "chrome" version
|
|
$(CURL_VERSION)/.chrome: $(chrome_libs) $(CURL_VERSION).tar.xz $(CURL_VERSION)/.patched-chrome
|
|
cd $(CURL_VERSION)
|
|
|
|
# Set up the configure flags to curl.
|
|
# If the user provided the --host flag to our configure script
|
|
# (for cross compilation), then pass it on to curl.
|
|
{ \
|
|
config_flags="--prefix=@prefix@"; \
|
|
config_flags="$$config_flags --with-nghttp2=$(nghttp2_install_dir)"; \
|
|
config_flags="$$config_flags --with-brotli=$(brotli_install_dir)"; \
|
|
config_flags="$$config_flags --with-openssl=$(boringssl_install_dir)"; \
|
|
config_flags="$$config_flags USE_CURL_SSLKEYLOGFILE=true"; \
|
|
if test "$(static_build)" = "yes"; then \
|
|
config_flags="$$config_flags --enable-static --disable-shared";
|
|
fi; \
|
|
if test -n "$(host_alias)"; then \
|
|
config_flags="$$config_flags --host=$(host_alias)"; \
|
|
fi; \
|
|
if test -n "$(with_zlib)"; then \
|
|
config_flags="$$config_flags --with-zlib=$(with_zlib)"; \
|
|
else \
|
|
config_flags+=" --with-zlib"; \
|
|
fi; \
|
|
if test -n "$(with_ca_bundle)"; then \
|
|
config_flags="$$config_flags --with-ca-bundle=$(with_ca_bundle)"; \
|
|
fi; \
|
|
if test -n "$(with_ca_path)"; then \
|
|
config_flags="$$config_flags --with-ca-path=$(with_ca_path)"; \
|
|
fi; \
|
|
add_libs="-pthread"; \
|
|
add_cflags="-I$(boringssl_install_dir)"; \
|
|
}
|
|
|
|
echo "Configuring curl with: $$config_flags"
|
|
|
|
./configure $$config_flags CFLAGS="$$add_cflags" LIBS="$$add_libs"
|
|
|
|
# Remove possible leftovers from a previous compilation
|
|
$(MAKE) clean MAKEFLAGS=
|
|
touch .chrome
|
|
# Remove the Firefox flag if it exists
|
|
rm -f .firefox
|