bash - 在 Bash 的/dev/tcp 中使用 SSL

标签 bash ssl tcp

我刚刚用 bash 编写了一个 IRC 机器人(我知道,我知道)。它完成了我需要的一切(SASL 身份验证、解析链接等),除了它不通过 SSL 连接。经过大量谷歌搜索和 IRC 上的大量麻烦之后,我还没有找到一种方法让/dev/tcp 使用 SSL。这是我当前的代码:

#!/bin/bash

if [[ "$1" == "-debug" ]]; then
    set -x
fi

irc_send() {
    printf ">>> %s\n" "$1"
    printf "%s\r\n" "$1" >&3 &
}

sasl_successful() {
    while read -ru3 line; do
        printf "%s\n" "$line"
        read -r location numeric rest <<< "$line"

        if [[ "$numeric" == "903" ]]; then
            return 0
        elif [[ "$numeric" == "904" || "$numeric" == "906" ]]; then
            return 1
        fi
    done
}

sasl_connect() {
    user="$1"
    pass="$2"
    server_pass="$3"
    nick="$4"
    ident="$5"
    realname="$6"
    saslstring="$(printf '%s\0%s\0%s' "$user" "$user" "$pass" | base64)"

    irc_send "CAP REQ :sasl"

    if [[ "$server_pass" ]]; then
        irc_send "PASS $server_pass"
    fi

    irc_send "NICK $nick"
    irc_send "USER $ident * * :$realname"
    irc_send "AUTHENTICATE PLAIN"
    irc_send "AUTHENTICATE $saslstring"

    if sasl_successful; then
        irc_send "CAP END"
        return 0
    else
        return 1
    fi
}

get_title() {
    xmllint --html --xpath '//title/text()' - <<< "$(curl -sL "$1")" 2> /dev/null
}

domain_base() {
    domain="$(python -c "import urlparse; print urlparse.urlparse('$1').netloc")"

    if [[ -z "$domain" ]]; then
        echo "$1"
    else
        echo "$domain"
    fi
}

links=(
    'http://static.giantbomb.com/uploads/square_small/2/25062/833357-link_avatar3.jpg'
    'http://vignette1.wikia.nocookie.net/zelda/images/2/2a/Fierce_Deity_Link.png/revision/latest?cb=20100124002042'
    'http://8wayrun.com/attachments/lnksc2art2-jpg.3846/'
    'https://camo.githubusercontent.com/9bb56499161ec0a5c20b6b3a3af674f51072af7c/687474703a2f2f7777772e6e6f727468636173746c652e636f2e756b2f6775696c642f6172742f616e6e615f6c2f6c696e6b312e6a7067'
    'http://www.jdubuzz.com/files/2015/05/Link_3_ST.png'
    'http://www.smashbros.com/images/og/link.jpg'
    'https://upload.wikimedia.org/wikipedia/en/3/39/Wakerlink.jpg'
)

host="irc.freenode.net"
server_pass=""
port=6667
nick="mewtwo"
user="mewtwo"
realname="A simple irc bot written in bash."
channels="#somechannel"
username="$1"
password="$2"

exec 3<>"/dev/tcp/$host/$port"

if ! sasl_connect "$username" "$password" "$server_pass" "$nick" "$user" "$realname"; then
    printf "Could not connect.\n" >&2
fi

irc_send "JOIN $channels"

while :; do
    irc_send "PING $RANDOM"
    sleep 1m
done &

while read -ru3 line; do
    line="$(perl -pe 's/\r\n/\n/' <<< "$line")"
    read -r from type target msg <<<  "$line"
    msg="${msg#:}" nick="${from#:}" nick="${nick%%!*}" host="${from%%@*}" host="${from#"$host"@}"

    # parsing logic
    if [[ "$type" == "PRIVMSG" ]]; then
        printf "[%s] %s@%s: %s\n" "$target" "$nick" "$host" "$msg" &
    else
        printf "%s\n" "$line" &
    fi

    # response logic
    if [[ "$type" == "PRIVMSG" ]]; then
        if [[ "$msg" == "link?" ]]; then
            irc_send "PRIVMSG $target :${links[RANDOM % ${#links[@]}]}"
        fi

        urls=($(grep -oPm 1 '(?:https?:\/\/)?([a-z\d-]*\.)?[a-z\d-]+\.[a-z]+(?:\/\S*)?(?(?<=\.(jpg|png|gif))(*SKIP)(*F))' <<< "$msg"))

        for url in "${urls[@]}"; do
            irc_send "PRIVMSG $target :[$(get_title "$url")] - $(domain_base "$url")"
        done
    fi
done

欢迎提出任何建议!

最佳答案

用 OpenSSL 打开 SSL socket 并用 stdin stdout 与它对话

openssl s_client irc.freenode.net:7070

关于bash - 在 Bash 的/dev/tcp 中使用 SSL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37251384/

相关文章:

linux - 如何使用 putty 运行 sudo 命令

c++ - 准备两个具有相同 SSL_CTX 状态的应用程序数据

c++ - RFC/建议 : On secure/unsecure rpc/event-stream protocol design

linux - Bash 脚本 : "Dump" directory using mv - current directory

bash - 如何在Docker容器中执行Shell脚本

wordpress - wordpress 中的重复页面 HTTP 和 HTTPS

python - 使用 Python 请求访问 Shibboleth 身份验证服务器时出现 SSL 错误

C 中的 CR/LF 条件检查

http - 杀死已经在使用的绑定(bind) tcp 连接

bash - 如何在 Bash 中读取文件或标准输入