CURL那些不太为人知但强大的功能

对每个人而言,真正的职责只有一个:找到自我。然后在心中坚守其一生,全心全意,永不停息。所有其它的路都是不完整的,是人的逃避方式,是对大众理想的懦弱回归,是随波逐流,是对内心的恐惧 ——赫尔曼·黑塞《德米安》

写在前面


  • 博文内容为 curl 不长用使用技巧简单整理
  • 理解不足小伙伴帮忙指正

对每个人而言,真正的职责只有一个:找到自我。然后在心中坚守其一生,全心全意,永不停息。所有其它的路都是不完整的,是人的逃避方式,是对大众理想的懦弱回归,是随波逐流,是对内心的恐惧 ——赫尔曼·黑塞《德米安》


curl

curl是用于从服务器传输数据或将数据传输到服务器的工具。它支持以下协议:DICT,FILE,FTP,FTPS,GOPHER,GOPHERS,HTTP,HTTPS,IMAP,IMAPS,LDAP,LDAPS,MQTT,POP3,POP3S,RTMP,RTMPS,RTSP,SCP,SFTP,SMB,SMBS,SMTP,SMTPS,TELNET,TFTP,WS和WSS。它由 libcurl 提供支持,适用于所有与传输相关的功能

一、性能分析:深度指标监控

全链路耗时分析 -w 模板, 传输速度统计

1
2
3
4
5
6
┌──[root@liruilongs.github.io]-[~] 
└─$curl -w "下载速度: %{speed_download} B/s\n上传速度: %{speed_upload} B/s\n" -o /dev/null -s https://example.com
下载速度: 1428 B/s
上传速度: 0 B/s
┌──[root@liruilongs.github.io]-[~]
└─$

限速测试--limit-rate 模拟弱网环境(限制 50KB/s):

1
2
3
4
5
┌──[root@liruilongs.github.io]-[~] 
└─$curl --limit-rate 50K -O http://example.com/bigfile.iso
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 1256 100 1256 0 0 1604 0 --:--:-- --:--:-- --:--:-- 1604

访问指标获取 ,同样使用-w 模版

200 的情况

1
2
3
4
5
6
7
8
9
┌──[liruilong@liruilongs.github.io]-[~]
└─$curl -w "总时间: %{time_total}s\n名称解析时间: %{time_namelookup}s\n连接时间: %{time_connect}s\nTLS握手时间: %{time_appconnect}s\n等待时间: %{time_starttransfer}s\n数据传输时间: %{time_total}s\nHTTP状态码: %{http_code}\n" -o /dev/null -s baidu.com -k
总时间: 0.050962s
名称解析时间: 0.003813s
连接时间: 0.022080s
TLS握手时间: 0.000000s
等待时间: 0.050661s
数据传输时间: 0.050962s
HTTP状态码: 200

500 的情况

1
2
3
4
5
6
7
8
9
10
11
┌──[liruilong@liruilongs.github.io]-[~]
└─$curl -w "总时间: %{time_total}s\n名称解析时间: %{time_namelookup}s\n连接时间: %{time_connect}s\nTLS握手时间: %{time_appconnect}s\n等待时间: %{time_starttransfer}s\n数据传输时间: %{time_total}s\nHTTP状态码: %{http_code}\n" -o /dev/null -s https://liruilong.blog.csdn.net/ -k
总时间: 0.257467s
名称解析时间: 0.044719s
连接时间: 0.084697s
TLS握手时间: 0.175856s
等待时间: 0.257414s
数据传输时间: 0.257467s
HTTP状态码: 521
┌──[liruilong@liruilongs.github.io]-[~]
└─$

更多的参数获取

https://everything.curl.dev/usingcurl/verbose/writeout.html#available---write-out-variables

当然也支持文件的方式配置模版

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
curl --silent --output /dev/null --show-error -w @format.txt http://example.com/

# Type: text/html; charset=UTF-8
# Code: 200
#
# From 8.1.0:
# Scheme: http
# Host: example.com
# Port: 80
#
# Read header content (v7.83.0):
# Server: Sat, 29 Jun 2024 13:01:30 GMT

# format.txt
Type: %{content_type}\nCode: %{response_code}\n\n

From 8.1.0:\n\n

Scheme: %{url.scheme}\n
Host: %{url.host}\n
Port: %{url.port}\n

Read header content (v7.83.0):\n
%header{date}

并行/并发测试

通过路径参数化生成多个相同URL的变体,测试服务器对路径无关请求的并发处理能力,触发并发请求:

  • --parallel-immediate 强制立即启动所有并行请求,而非按队列逐个触发。
  • --parallel-max 3 限制同时活跃的最大连接数为 3
  • --parallel 启用并行请求模式,允许同时处理多个连接。
1
2
curl -I --parallel --parallel-immediate  --parallel-max 3 "https://example.com/[1-3]"
curl -I --parallel --parallel-immediate --parallel-max 3 stackoverflow.com google.com example.com

也可以通过 ​**–config 参数** 指定包含多个相同域名 URL 的配置文件(urls.conf):

1
2
3
4
5
6
7
# urls.conf 内容
url = "https://example.com"
url = "https://example.com"
url = "https://example.com"

# 执行命令
curl -I --parallel --parallel-immediate --parallel-max 3 --config urls.conf

二、协议魔改:突破常规请求方式

模拟浏览器访问 :通过 -H 自定义 User-Agent 伪装成 Chrome:

1
2
3
4
5
6
7
8
9
10
┌──[root@liruilongs.github.io]-[~] 
└─$curl -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/91.0.4472.124" https://example.com
<!doctype html>
<html>
<head>
<title>Example Domain</title>
。。。。。。。。。。。。。。。。。。。。。
</html>
┌──[root@liruilongs.github.io]-[~]
└─$

绕过 DNS 直接指定 IP :用 --resolve 强制解析域名到指定 IP(适用于测试 CDN 节点):

1
2
3
4
5
6
┌──[root@liruilongs.github.io]-[~] 
└─$curl https://example.com --resolve example.com:443:23.215.0.136
<!doctype html>
<html>
<head>
<title>Example Domain</title>

强制使用特定的本地网络接口 --interface 指定使用的网卡

1
curl --interface wlp5s0 https://example.com

强制使用特定的 DNS 服务器 --dns-ipv4-addr

1
curl --dns-ipv4-addr 1.1.1.1 https://example.com

Telnet 协议探测端口 :端口连通性测试,

通的情况

1
2
3
4
5
┌──[root@vms100.liruilongs.github.io]-[~]
└─$timeout 3 curl -vvv telnet://192.168.26.55:55555
* About to connect() to 192.168.26.55 port 55555 (#0)
* Trying 192.168.26.55...
* Connected to 192.168.26.55 (192.168.26.55) port 55555 (#0)

不通的情况

1
2
3
4
5
6
7
8
9
10
┌──[root@vms100.liruilongs.github.io]-[~]
└─$timeout 3 curl -vvv telnet://192.168.26.55:443
* About to connect() to 192.168.26.55 port 443 (#0)
* Trying 192.168.26.55...
* 拒绝连接
* Failed connect to 192.168.26.55:443; 拒绝连接
* Closing connection 0
curl: (7) Failed connect to 192.168.26.55:443; 拒绝连接
┌──[root@vms100.liruilongs.github.io]-[~]
└─$

三、调试黑科技:逆向工程师最爱

显示完整通信过程 -v 输出详细通信日志(含 SSL 握手):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
┌──[root@liruilongs.github.io]-[~] 
└─$curl -v --tlsv1.2 https://example.com
* Trying 96.7.128.198:443...
* Connected to example.com (96.7.128.198) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
* CApath: none
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x5652e145a9b0)
> GET / HTTP/2
> Host: example.com
> user-agent: curl/7.79.1
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
< cache-control: max-age=1907
< date: Tue, 25 Mar 2025 17:35:20 GMT
< alt-svc: h3=":443"; ma=93600,h3-29=":443"; ma=93600,quic=":443"; ma=93600; v="43"
< content-length: 1256
<
<!doctype html>
<html>
<head>
<title>Example Domain</title>

强制忽略 SSL 证书验证-k 绕过 HTTPS 证书检查(测试环境专用):

1
2
3
4
5
6
┌──[root@liruilongs.github.io]-[~] 
└─$curl -k https://example.com
<!doctype html>
<html>
<head>
<title>Example Domain</title>

原始报文捕获 :用 --trace-ascii 输出二进制通信记录:

1
2
3
4
5
6
7
┌──[root@liruilongs.github.io]-[~] 
└─$curl --trace-ascii debug.log https://example.com
<!doctype html>
<html>
<head>
<title>Example Domain</title>
··........

输出的报文

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
┌──[root@liruilongs.github.io]-[~] 
└─$cat debug.log
== Info: Trying 96.7.128.175:443...
== Info: Connected to example.com (96.7.128.175) port 443 (#0)
== Info: ALPN, offering h2
== Info: ALPN, offering http/1.1
== Info: successfully set certificate verify locations:
== Info: CAfile: /etc/pki/tls/certs/ca-bundle.crt
== Info: CApath: none
=> Send SSL data, 5 bytes (0x5)
0000: .....
== Info: TLSv1.3 (OUT), TLS handshake, Client hello (1):
=> Send SSL data, 512 bytes (0x200)
0000: ..............0%i[S.......N<.H.d.u.... e.k..M77....0_|.(...&..*
0040: ........>.......,.0.........+./...$.(.k.#.'.g.....9.....3.....=.
0080: <.5./.....u.........example.com........................3t.......
''.........................''
0240: cert.com/CPS0...U...........0...U.%..0...+.........+.......0....
0280: U.....0..0H.F.D.Bhttp://crl3.digicert.com/DigiCertGlobalG3TLSECC

四、请求定制:高级数据处理技巧

发送 JSON 数据并压缩 结合 --compressed 启用压缩传输:

1
curl -X POST -H "Content-Type: application/json" --data '{"key":"value"}' --compressed https://api.example.com

多文件上传 使用 -F 批量上传文件(支持通配符):

1
curl -F "files=@/path/to/images/*.png" https://upload.example.com

断点续传 -C - 自动续传未完成下载:

1
curl -C - -O http://example.com/largefile.zip

五、协议全家桶:非 HTTP 玩法

除了上面的 telnet 之外,还支持下面的一些操作

FTP 文件操作 :上传/下载文件到 FTP 服务器:

1
2
curl -u user:pass -T localfile.txt ftp://ftp.example.com/remote/
curl -O ftp://user:pass@ftp.example.com/remote/file.zip

发送 SMTP 邮件 :通过 curl 直接发送邮件:

1
curl --mail-from sender@example.com --mail-rcpt receiver@example.com --upload-file email.txt smtp://smtp.example.com

博文部分内容参考

© 文中涉及参考链接内容版权归原作者所有,如有侵权请告知,这是一个开源项目,如果你认可它,不要吝啬星星哦 :)


https://martinheinz.dev/blog/113


© 2018-至今 liruilonger@gmail.com, All rights reserved. 保持署名-非商用-相同方式共享(CC BY-NC-SA 4.0)

发布于

2024-01-31

更新于

2025-03-26

许可协议

评论
Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×