Search code examples
curlcontainerstelnet

close curl connection after telnet


What I Want:

After a successful connection, I want curl to exit successfully. I am running this command inside a container, so I want the curl command to exit successfully so that the container will too.

Here is my example:

$ curl -v telnet://google.com:443/
*   Trying 172.217.197.113...
* TCP_NODELAY set
* Connected to google.com (172.217.197.113) port 443 (#0)

Options I have tried:

No Keep Alive:

$ curl -v --no-keepalive telnet://google.com:443/
*   Trying 172.217.197.102...
* TCP_NODELAY set
* Connected to google.com (172.217.197.102) port 443 (#0)

Connection Timeout:

$ curl -v --connect-timeout 5 telnet://google.com:443/
*   Trying 172.217.197.139...
* TCP_NODELAY set
* Connected to google.com (172.217.197.139) port 443 (#0)

Keep Alive Time:

$ curl -v --keepalive-time 5 telnet://google.com:443/
*   Trying 172.217.197.139...
* TCP_NODELAY set
* Connected to google.com (172.217.197.139) port 443 (#0)

Flag Definitions

--no-keepalive (Disable keepalive use on the connection)

--connect-timeout (SECONDS Maximum time allowed for connection)

--keepalive-time (SECONDS Wait SECONDS between keepalive probes)


Solution

  • To make curl exit immediately upon a successful telnet connection, purposely pass an unknown telnet option and test if the exit code is 48:

    curl --telnet-option 'BOGUS=1' --connect-timeout 2 -s telnet://google.com:443 </dev/null
    code=$?
    if [ "$code" -eq 48 ]; then
      echo "Telnet connection was successful"
    else
      echo "Telnet connection failed. Curl exit code was $code"
    fi
    

    We purposely passed an unknown telnet option, BOGUS=1, to curl's -t, --telnet-option option. Replace BOGUS with any name you want other than the three supported options of TTYPE, XDISPLOC, or NEW_ENV.

    48 is curl's error code for "CURLE_UNKNOWN_OPTION (48) An option passed to libcurl is not recognized/known."

    This works because the telnet options are processed only after a successful connection.

    Slight variation

    Purposely pass a telnet option with bad syntax, such as BOGUS or an empty string, and test for an exit code of 49 (CURLE_SETOPT_OPTION_SYNTAX). We use this approach in the following function. As before, this works because curl processes the telnet options only after a successful connection.

    Formalized as a function

    # Args:
    # 1 - host
    # 2 - port
    tcp_port_is_open() {
       local code
       curl --telnet-option BOGUS --connect-timeout 2 -s telnet://"$1:$2" </dev/null
       code=$?
       case $code in
         49) return 0 ;;
         *) return "$code" ;;
       esac
    } 
    

    Tests

    tcp_port_is_open example.com 80
    echo "$?"
    # 0 ✔️
    
    tcp_port_is_open example.com 1234
    echo "$?"
    # 28 - Operation timeout ✔️
    
    tcp_port_is_open nonexistent.example.com 80
    echo "$?"
    # 6 - Couldn't resolve host. ✔️
    

    Edit: May 27, 2022: Watch this todo item

    https://curl.se/docs/todo.html#exit_immediately_upon_connection
    Via: https://curl.se/mail/archive-2022-04/0027.html