Skip to content

fortio/multicurl

Folders and files

NameName
Last commit message
Last commit date
Sep 17, 2024
Sep 17, 2024
Mar 21, 2024
Jun 23, 2024
Jun 23, 2024
Jan 27, 2023
Sep 17, 2024
Mar 29, 2023
Sep 17, 2024
Sep 17, 2024
Mar 29, 2023

Repository files navigation

codecov

multicurl

Fetches a URL from all the IPs of a given host. Optionally repeat until an expected result code is obtained from all addresses. It will also print information about certificates, including the shortest expiration found.

Installation

If you have a recent go installation already:

CGO_ENABLED=0 go install fortio.org/multicurl@latest

Or get on of the binary releases

Or using the docker image

docker run fortio/multicurl http://debug.fortio.org/test

Or using brew (mac)

brew install fortio/tap/multicurl

Usage

multicurl https://debug.fortio.org/test

Use -4 for ipv4 only, -6 for ipv6 only, otherwise it'll try all of them.

flags:
  -4    Use only IPv4
  -6    Use only IPv6
  -H key:value
        Additional http header(s). Multiple key:value pairs can be passed using multiple -H.
  -I file
        IP address file to use instead of resolving the URL, use - for stdin
  -X string
        HTTP method to use, default is GET unless -d is set which defaults to POST
  -cacert file
        Path to a custom CA certificate file to use instead of system ones.
  -cert file
        Path to a custom client certificate file for mTLS.
  -cert-expiry days
        Certificate expiry error threshold in days (default 7)
  -d string
        Payload to POST, use @filename to read from file
  -expected int
        Expected HTTP return code, 0 means any and non 200s will be warning otherwise if
set any different code is an error
  -i    Include response headers in output
  -insecure
        Skip verification of server certificate (insecure TLS)
  -json
        JSON output of summary results
  -key file
        Path to a custom client key file for mTLS.
  -loglevel level
        log level, one of [Debug Verbose Info Warning Error Critical Fatal] (default Info)
  -n int
        Max number of IPs to use/try (0 means all the ones found)
  -o file name pattern
        Output file name pattern, e.g "out-%.html" where % will be replaced by the ip,
default is stdout, use "none" for no output (in combination with -json for instance)
  -quiet
        Quiet mode, sets loglevel to Error (quietly) to reduces the output
  -relookup
        Re-lookup the URL between each repeat
  -repeat int
        Max number of times to retry on errors if positive, default is 0 (no retry),
negative is retry until -total-timeout
  -repeat-delay duration
        Delay between retries (default 5s)
  -request-timeout duration
        HTTP method (default 3s)
  -total-timeout duration
        HTTP method (default 30s)

Note that -relookup works better on CGO_ENABLED=0 built binary, otherwise the OS library caches the results.

Note that -H Host:xxx https://yyyy/ is a special header and using that will be the same as querying https://xxx/ using the IPs of yyy (convenient to test a virtual host against a LoadBalancer or ingress name before the DNS is updated)

See also multicurl.txtar for examples (tests)

Example

Regular

$ multicurl -expected 301 -repeat 2 -n 2 -relookup debug.fortio.org
11:49:20 I Fortio multicurl dev  go1.19.5 arm64 darwin, using resolver ip, GET debug.fortio.org
11:49:20 I Resolved ip debug.fortio.org:http to port 80 and 6 addresses [18.222.136.83 192.9.142.5 192.9.227.83 2600:1f16:9c6:b400:282c:a766:6cab:4e82 2603:c024:c00a:d144:6663:5896:7efb:fbf3 2603:c024:c00a:d144:7cd0:4951:7106:96b8] - keeping first 2
11:49:20 E 1: Status 200 "200 OK" from 18.222.136.83
Φορτίο version 1.40.1 h1:D1H+5aOnauTr4WTnopHl1MhSZt/l0Asi3ZEqkpBwT0c= go1.19.5 arm64 linux (in fortio.org/proxy 1.8.1)
Debug server on a1 up for 37h43m3s
Request from 216.194.105.159:4496

GET / HTTP/1.1

headers:

Host: debug.fortio.org
Accept-Encoding: gzip
Connection: close
User-Agent: fortio.org/multicurl-dev

body:


11:49:20 E 2: Status 200 "200 OK" from 192.9.142.5
Φορτίο version 1.40.1 h1:D1H+5aOnauTr4WTnopHl1MhSZt/l0Asi3ZEqkpBwT0c= go1.19.5 arm64 linux (in fortio.org/proxy 1.8.1)
Debug server on oa1 up for 23h55m4.5s
Request from 216.194.105.159:4497

GET / HTTP/1.1

headers:

Host: debug.fortio.org
Accept-Encoding: gzip
Connection: close
User-Agent: fortio.org/multicurl-dev

body:


11:49:20 E [1] 2 errors (0 warnings)
11:49:25 I Resolved ip debug.fortio.org:http to port 80 and 6 addresses [18.222.136.83 192.9.142.5 192.9.227.83 2603:c024:c00a:d144:7cd0:4951:7106:96b8 2600:1f16:9c6:b400:282c:a766:6cab:4e82 2603:c024:c00a:d144:6663:5896:7efb:fbf3] - keeping first 2
11:49:26 E 1: Status 200 "200 OK" from 18.222.136.83
Φορτίο version 1.40.1 h1:D1H+5aOnauTr4WTnopHl1MhSZt/l0Asi3ZEqkpBwT0c= go1.19.5 arm64 linux (in fortio.org/proxy 1.8.1)
Debug server on a1 up for 37h43m8.5s
Request from 216.194.105.159:4624

GET / HTTP/1.1

headers:

Host: debug.fortio.org
Accept-Encoding: gzip
Connection: close
User-Agent: fortio.org/multicurl-dev

body:


11:49:26 E 2: Status 200 "200 OK" from 192.9.142.5
Φορτίο version 1.40.1 h1:D1H+5aOnauTr4WTnopHl1MhSZt/l0Asi3ZEqkpBwT0c= go1.19.5 arm64 linux (in fortio.org/proxy 1.8.1)
Debug server on oa1 up for 23h55m10s
Request from 216.194.105.159:4625

GET / HTTP/1.1

headers:

Host: debug.fortio.org
Accept-Encoding: gzip
Connection: close
User-Agent: fortio.org/multicurl-dev

body:


11:49:26 E [2] 2 errors (0 warnings)
11:49:31 I Resolved ip debug.fortio.org:http to port 80 and 6 addresses [192.9.227.83 18.222.136.83 192.9.142.5 2600:1f16:9c6:b400:282c:a766:6cab:4e82 2603:c024:c00a:d144:6663:5896:7efb:fbf3 2603:c024:c00a:d144:7cd0:4951:7106:96b8] - keeping first 2
11:49:31 E 1: Status 200 "200 OK" from 192.9.227.83
Φορτίο version 1.40.1 h1:D1H+5aOnauTr4WTnopHl1MhSZt/l0Asi3ZEqkpBwT0c= go1.19.5 amd64 linux (in fortio.org/proxy 1.8.1)
Debug server on ol1 up for 37h36m2.9s
Request from 216.194.105.159:4784

GET / HTTP/1.1

headers:

Host: debug.fortio.org
Accept-Encoding: gzip
Connection: close
User-Agent: fortio.org/multicurl-dev

body:


11:49:31 E 2: Status 200 "200 OK" from 18.222.136.83
Φορτίο version 1.40.1 h1:D1H+5aOnauTr4WTnopHl1MhSZt/l0Asi3ZEqkpBwT0c= go1.19.5 arm64 linux (in fortio.org/proxy 1.8.1)
Debug server on a1 up for 37h43m14.2s
Request from 216.194.105.157:4528

GET / HTTP/1.1

headers:

Host: debug.fortio.org
Accept-Encoding: gzip
Connection: close
User-Agent: fortio.org/multicurl-dev

body:


11:49:31 E [3] 2 errors (0 warnings)
11:49:31 E Reached max repeat 2
11:49:31 I Total iterations: 3, errors: 6, warnings 0
exit status 2

Certificate information

% multicurl -4 -cert-expiry 60 https://debug.fortio.org > /dev/null

Yields

12:46:54 I Fortio multicurl dev  go1.19.6 arm64 darwin, using resolver ip4, GET https://debug.fortio.org
12:46:55 I Resolved ip4 debug.fortio.org:https to port 443 and 3 addresses [192.9.142.5 18.222.136.83 192.9.227.83]
12:46:55 I 1: Status 200 "200 OK" from 192.9.142.5
12:46:55 I Certificate "CN=debug.fortio.org" expires in 52 days
12:46:55 I Certificate "CN=R3,O=Let's Encrypt,C=US" expires in 925 days
12:46:55 I Certificate "CN=ISRG Root X1,O=Internet Security Research Group,C=US" expires in 575 days
12:46:55 I 2: Status 200 "200 OK" from 18.222.136.83
12:46:55 I Certificate "CN=debug.fortio.org" expires in 51 days
12:46:55 I Certificate "CN=R3,O=Let's Encrypt,C=US" expires in 925 days
12:46:55 I Certificate "CN=ISRG Root X1,O=Internet Security Research Group,C=US" expires in 575 days
12:46:55 I 3: Status 200 "200 OK" from 192.9.227.83
12:46:55 I Certificate "CN=debug.fortio.org" expires in 52 days
12:46:55 I Certificate "CN=R3,O=Let's Encrypt,C=US" expires in 925 days
12:46:55 I Certificate "CN=ISRG Root X1,O=Internet Security Research Group,C=US" expires in 575 days
12:46:55 I [1] 0 errors (0 warnings)
12:46:55 E Shortest cert expiry is 2023-04-26 02:13:27 +0000 UTC (51.2 days from now)
12:46:55 I Total iterations: 1, errors: 0, warnings 0
exit status 1

JSON output

multicurl -json -quiet -o none https://debug.fortio.org | jq

Yields

{
 "Errors": 0,
 "Warnings": 0,
 "Addresses": [
   "2603:c024:c00a:d144:6663:5896:7efb:fbf3",
   "2603:c024:c00a:d144:7cd0:4951:7106:96b8",
   "2600:1f16:9c6:b400:282c:a766:6cab:4e82",
   "192.9.142.5",
   "192.9.227.83",
   "18.222.136.83"
 ],
 "Codes": {
   "18.222.136.83:443": 200,
   "192.9.142.5:443": 200,
   "192.9.227.83:443": 200,
   "[2600:1f16:9c6:b400:282c:a766:6cab:4e82]:443": 200,
   "[2603:c024:c00a:d144:6663:5896:7efb:fbf3]:443": 200,
   "[2603:c024:c00a:d144:7cd0:4951:7106:96b8]:443": 200
 },
 "Sizes": {
   "18.222.136.83:443": 339,
   "192.9.142.5:443": 340,
   "192.9.227.83:443": 340,
   "[2600:1f16:9c6:b400:282c:a766:6cab:4e82]:443": 369,
   "[2603:c024:c00a:d144:6663:5896:7efb:fbf3]:443": 370,
   "[2603:c024:c00a:d144:7cd0:4951:7106:96b8]:443": 370
 },
 "Iterations": 1,
 "ShortestCertExpiry": "2023-04-26T02:13:27Z"
}

Note the handy ShortestCertExpiry entry.

ps: this started as https://pkg.go.dev/github.com/fortio/multicurl and now is available under https://pkg.go.dev/fortio.org/multicurl