将 SSL 与 Bash 的 /dev/tcp 一起使用
Posted
技术标签:
【中文标题】将 SSL 与 Bash 的 /dev/tcp 一起使用【英文标题】:Using SSL with Bash's /dev/tcp 【发布时间】:2016-09-12 02:14:26 【问题描述】:我刚刚用 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
欢迎提出任何建议!
【问题讨论】:
"让 /dev/tcp 使用 SSL" 但为什么呢? TLS 已经这么复杂了……为什么不直接设置一个本地通道呢?它会很好地为您处理 TLS,您只需通过 TCP/IP 在本地连接到它。 TLS 要求在交换任何数据之前在 TCP 之上进行各种交换,我怀疑您是否可以简单地在 bash 中重做,即使不考虑性能和安全限制。 我也使用这种技术来检查我的家庭网络上的端口可用性。很高兴知道如何使用 SSL。我刚刚遇到您的问题,正在寻找自己的答案。 【参考方案1】:使用 OpenSSL 打开 SSL 套接字并使用 stdin stdout 与之对话
openssl s_client irc.freenode.net:7070
【讨论】:
以上是关于将 SSL 与 Bash 的 /dev/tcp 一起使用的主要内容,如果未能解决你的问题,请参考以下文章