Linux ELF Exploration
利用周末时间,系统性地总结下了关于 Linux ELF 以及动态链接相关的基础知识。
利用周末时间,系统性地总结下了关于 Linux ELF 以及动态链接相关的基础知识。
最近在做嵌入式平台上的 Chromium 移植工作,由于 Chromium 在 Linux 平台下需要依赖系统的 NSS 库,但是目标平台并没有这个库,只好自己移植一下。
获取最新的 Mozilla NSS 库源码包,这里我们下载 NSS NSPR 二合一包:
1 2 3 | wget https://ftp.mozilla.org/pub/security/nss/releases/NSS_3_43_RTM/src/nss-3.43-with-nspr-4.21.tar.gz tar -zxvpf nss-3.43-with-nspr-4.21.tar.gz cd nss-3.43 |
由于 NSS 依赖 NSPR,我们需要首先编译 NSPR 库:
1 2 3 4 5 | cd nspr CC=arm-none-linux-gnueabi-gcc CCC=arm-none-linux-gnueabi-g++ \ AR=arm-none-linux-gnueabi-ar RANLIB=arm-none-linux-gnueabi-ranlib \ ./configure --target=arm-linux --cache-file=/dev/null --prefix=$PWD/../dist make && make install |
由于 NSS 库的编译脚本默认使用 GYP 编译,需要先配置一下环境:
1 2 | cd ~/ && git clone https://chromium.googlesource.com/external/gyp export PATH=$HOME/gyp:$PATH |
先修改一下 coreconf/shlibsign.py 这个脚本,将下面一行注释,不然报错:
1 | # subprocess.check_call([os.path.join(bin_path, 'shlibsign'), '-v', '-i', lib_file], env=env, stdout=dev_null, stderr=dev_null) |
然后就可以开始编译 NSS 库了:
1 2 3 4 | cd nss CC=arm-none-linux-gnueabi-gcc CCC=arm-none-linux-gnueabi-g++ \ AR=arm-none-linux-gnueabi-ar RANLIB=arm-none-linux-gnueabi-ranlib \ ./build.sh --with-nspr=$PWD/../dist/include/nspr:$PWD/../dist/lib --target=arm |
注:nss-3.43/dist 为编译 out 目录,编译完后 include/lib 都在里面了。
WireGuard 是 ason A. Donenfeld 开发的一款点对点 VPN 协议,非常先进并且开源。在老司机的强烈推荐下,忍不住折腾了一番。本文旨在整理折腾记录并存档。
注:笔者的用的服务器是 GCE 上的 VM 实例,采用 Debian 9 发行版。其他发行版的安装过程可以参考 WireGuard Installstion 。
首先需要安装当前 Linux 内核对应的 linux_headers:
1 2 | apt update apt install linux-headers-$(uname -r) -y |
由于 WireGuard 比较新,尚在 Debian 不稳定版的源里,需要手动导入:
1 2 3 4 | echo "deb http://deb.debian.org/debian/ unstable main" > /etc/apt/sources.list.d/unstable.list printf 'Package: *\nPin: release a=unstable\nPin-Priority: 150\n' > /etc/apt/preferences.d/limit-unstable apt update apt install wireguard-dkms wireguard-tools resolvconf -y |
开启 IPV4 流量转发:
1 2 | echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf sysctl -p |
创建 WireGuard 配置文件夹,并生成服务端和客户端密钥对:
1 2 3 4 5 | mkdir -p /etc/wireguard && chmod 0777 /etc/wireguard cd /etc/wireguard umask 077 wg genkey | tee server_privatekey | wg pubkey > server_publickey wg genkey | tee client_privatekey | wg pubkey > client_publickey |
我们还需要使用 ifconfig 命令获取服务器的网卡名称并记录下来,下面以 eth0 为例。
生成服务器配置文件 /etc/wireguard/wg0.conf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | # eth0 换成实际网卡名, ListenPort为端口号 # 以下内容一次性粘贴执行,不要分行执行 echo " [Interface] PrivateKey = $(cat server_privatekey) Address = 10.0.0.1/24 PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE ListenPort = 50814 DNS = 8.8.8.8 MTU = 1420 [Peer] PublicKey = $(cat client_publickey) AllowedIPs = 10.0.0.2/32 " > wg0.conf |
这样服务端就算配置完成,可以启动 WireGuard了,使用方法如下:
1 2 3 4 5 6 7 8 | # 启动 WireGuard wg-quick up wg0 # 停止 WireGuard wg-quick down wg0 # 查看WireGuard运行状态 wg |
设置 wireguard 开机自启:
1 | systemctl enable wg-quick@wg0 |
客户端也同样需要安装 WireGuard,例如笔者所使用的 ArchLinux 上安装步骤如下:
1 | pacman -S wireguard-arch wireguard-tools |
在配置服务端时,我们在服务器上分别创建了服务端和客户端的密钥对,这样也便于我们生成客户端的配置文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | # Endpoint是服务器 ip 和服务端配置文件中设置的端口号 # 以下内容一次性粘贴执行,不要分行执行 echo " [Interface] PrivateKey = $(cat client_privatekey) Address = 10.0.0.2/24 DNS = 8.8.8.8 MTU = 1420 [Peer] PublicKey = $(cat server_publickey) Endpoint = 1.2.3.4:25108 AllowedIPs = 0.0.0.0/0, ::0/0 PersistentKeepalive = 25 " > client.conf |
生成后的客户端文件在服务器上,我们可以将其拷贝到 PC 客户端,或者通过生成二维码的方式导到移动客户端:
1 2 | apt install qrencode -y qrencode -t ansiutf8 < /etc/wireguard/client.conf |
这样使用手机客户端直接扫描生成二维码就可以快速完成配置。
由于同一个客户端配置只能同时用于一台设备连接,所以如果需要同时使用多个客户端的话,可以建立多个客户端配置。
停止服务端的 WireGuard:
1 | wg-quick down wg0 |
生成新的客户端密钥对:
1 | wg genkey | tee client0_privatekey | wg pubkey > client0_publickey |
在服务端配置文件中加入新的客户端公钥,并重新定义一段 AllowedIPs:
1 2 3 4 5 | # 一次性复制粘贴,不要分行执行 echo " [Peer] PublicKey = $(cat client0_publickey) AllowedIPs = 10.0.0.3/32" >> wg0.conf |
新建一个客户端文件,使用新客户端密钥的私钥:
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 一次性复制粘贴,不要分行执行 echo " [Interface] PrivateKey = $(cat client0_privatekey) Address = 10.0.0.3/24 DNS = 8.8.8.8 MTU = 1420 [Peer] PublicKey = $(cat server_publickey) Endpoint = 1.2.3.4:50814 AllowedIPs = 0.0.0.0/0, ::0/0 PersistentKeepalive = 25 " > client0.conf |
注意这里的 Address 与上面服务端新加的 AllowedIPs 保持一致,Endpoint 和之前的一样,为服务端的 IP 和 ListenPort。
搞好服务端和新增客户端的配置后,再重新启动服务端的 WireGuard:
1 | wg-quick up wg0 |
导出客户端配置文件方式依然可以采用上面介绍的方法导入到客户端。如果还需要添加新的 Peer,再次使用同样的方法操作即可。
经过实测,WireGuard 比笔者在另一台相同配置的 VM 实例上搭建的 V2Ray 结合 BBR 加速还要快,体验非常棒。