curl ftp.example.net でFTPが使われる
curlコマンドで宛先ホスト名だけを指定した場合かならず http:// になると思っていたが、http 以外が使われるケースがある
例えば curl ftp.jp.debian.org は ftp が選択される
$ curl -v ftp.jp.debian.org/debian/
* Trying 133.5.166.3:21...
* Connected to ftp.jp.debian.org (133.5.166.3) port 21 (#0)
< 220
> USER anonymous
< 331 Anonymous login ok, send your complete email address as your password
> PASS ftp@example.com
< 230 Anonymous access granted, restrictions apply
> PWD
< 257 "/" is the current directory
* Entry path is '/'
> CWD debian
* ftp_perform ends with SECONDARY: 0
< 250 CWD command successful
> EPSV
* Connect data stream passively
< 229 Entering Extended Passive Mode (|||13370|)
* Trying 133.5.166.3:13370...
* Connecting to 133.5.166.3 (133.5.166.3) port 13370
* Connected to ftp.jp.debian.org (133.5.166.3) port 21 (#0)
> TYPE A
< 200 Type set to A
> LIST
< 150 Opening ASCII mode data connection for file list
* Maxdownload = -1
drwxr-xr-x 25 ftp ftp 4096 Dec 17 09:30 dists
drwxr-xr-x 4 ftp ftp 4096 Feb 24 07:57 doc
-rw-r--r-- 1 ftp ftp 250667 Feb 24 08:30 extrafiles
drwxr-xr-x 3 ftp ftp 8192 Feb 24 08:23 indices
-rw-r--r-- 1 ftp ftp 17450143 Feb 24 08:23 ls-lR.gz
drwxr-xr-x 6 ftp ftp 90 Oct 5 17:09 pool
drwxr-xr-x 4 ftp ftp 51 Nov 17 2008 project
-rw-r--r-- 1 ftp ftp 1327 Dec 17 09:29 README
-rw-r--r-- 1 ftp ftp 1290 Jun 26 2010 README.CD-manufacture
-rw-r--r-- 1 ftp ftp 3210 Dec 17 09:29 README.html
-rw-r--r-- 1 ftp ftp 291 Mar 4 2017 README.mirrors.html
-rw-r--r-- 1 ftp ftp 86 Mar 4 2017 README.mirrors.txt
drwxr-xr-x 3 ftp ftp 61 Oct 10 2012 tools
drwxr-xr-x 26 ftp ftp 4096 Aug 14 2021 zzz-dists
* Remembering we are in dir "debian/"
< 226 Transfer complete
* Connection #0 to host ftp.jp.debian.org left intact
この辺だろうか どうやらドメインの先頭がこれらと一致した場合にhttp以外が選択されるらしい
https://github.com/curl/curl/blob/801bd5138ce31aa0d906fa4e2eabfc599d74e793/lib/urlapi.c#L1117-L1132
...
if((flags & CURLU_GUESS_SCHEME) && !schemep) {
/* legacy curl-style guess based on host name */
if(checkprefix("ftp.", hostname))
schemep = "ftp";
else if(checkprefix("dict.", hostname))
schemep = "dict";
else if(checkprefix("ldap.", hostname))
schemep = "ldap";
else if(checkprefix("imap.", hostname))
schemep = "imap";
else if(checkprefix("smtp.", hostname))
schemep = "smtp";
else if(checkprefix("pop3.", hostname))
schemep = "pop3";
else
schemep = "http";
...
無理やり名前解決させて試してみた。
dict というのは Dictionary Server Protocol
というもので、ポート 2628 を使うらしい
$ curl --version
curl 7.81.0 (x86_64-pc-linux-gnu) libcurl/7.81.0 OpenSSL/3.0.2 zlib/1.2.11 brotli/1.0.9 zstd/1.4.8 libidn2/2.3.2 libpsl/0.21.0 (+libidn2/2.3.2) libssh/0.9.6/openssl/zlib nghttp2/1.43.0 librtmp/2.3 OpenLDAP/2.5.13
Release-Date: 2022-01-05
Protocols: dict file ftp ftps gopher gophers http https imap imaps ldap ldaps mqtt pop3 pop3s rtmp rtsp scp sftp smb smbs smtp smtps telnet tftp
Features: alt-svc AsynchDNS brotli GSS-API HSTS HTTP2 HTTPS-proxy IDN IPv6 Kerberos Largefile libz NTLM NTLM_WB PSL SPNEGO SSL TLS-SRP UnixSockets zstd
$ curl --resolve ftp.example.net:21:127.0.0.1 ftp.example.net
curl: (7) Failed to connect to ftp.example.net port 21 after 0 ms: Connection refused
$ curl --resolve dict.example.net:2628:127.0.0.1 dict.example.net
curl: (7) Failed to connect to dict.example.net port 2628 after 0 ms: Connection refused
$ curl --resolve ldap.example.net:389:127.0.0.1 ldap.example.net
curl: (7) Failed to connect to ldap.example.net port 389 after 0 ms: Connection refused
$ curl --resolve imap.example.net:143:127.0.0.1 imap.example.net
curl: (7) Failed to connect to imap.example.net port 143 after 0 ms: Connection refused
$ curl --resolve smtp.example.net:25:127.0.0.1 smtp.example.net
curl: (7) Failed to connect to smtp.example.net port 25 after 0 ms: Connection refused
$ curl --resolve pop3.example.net:110:127.0.0.1 pop3.example.net
curl: (7) Failed to connect to pop3.example.net port 110 after 0 ms: Connection refused