Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 77 additions & 1 deletion settings/settings-sshd.env
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,14 @@ validate_devworkspace() {

resolve_devworkspace_pod || return 1

oc exec -n ${DEVWORKSPACE_NS} ${podName} -c ${mainContainerName} -- cat /tmp/sshd.log &>/dev/null #always quiet this message an rely on return code
res=$(oc exec -n ${DEVWORKSPACE_NS} ${podName} -c ${mainContainerName} -- sh -c 'cat /tmp/sshd.log || { ret=$?; cat /tmp/poststart-stdout.txt /tmp/poststart-stderr.txt /proc/net/tcp /proc/net/tcp6; exit $ret; }')
if [ $? -eq 1 ]; then
# fail to cat ssh log file
log "Failed to cat /tmp/sshd.log file on container"
proc_net_tcp=$(echo "${res}" | sed -n '/local_address/,/local_address/ p' | head -n -1)
proc_net_tcp6=$(echo "${res}" | tac | sed -n '1,/local_address/ p' | tac)
log "$(echo "${proc_net_tcp}" | proc_tcp)"
log "$(echo "${proc_net_tcp6}" | proc_tcp)"
return 1
fi
res=$(oc exec -n ${DEVWORKSPACE_NS} ${podName} -c ${mainContainerName} -- cat /tmp/sshd.log | grep -q 'Server listening on')
Expand All @@ -37,3 +41,75 @@ validate_devworkspace() {
return 1
fi
}

function proc_tcp () {
# Define TCP States mapped from hex values
declare -A states=(
["01"]="ESTABLISHED" ["02"]="SYN_SENT" ["03"]="SYN_RECV"
["04"]="FIN_WAIT1" ["05"]="FIN_WAIT2" ["06"]="TIME_WAIT"
["07"]="CLOSE" ["08"]="CLOSE_WAIT" ["09"]="LAST_ACK"
["0A"]="LISTEN" ["0B"]="CLOSING"
)

# Print headers
printf "%-20s %-20s %-12s %-20s %-6s %-50s\n" "LOCAL ADDRESS" "REMOTE ADDRESS" "STATE" "UID" "INODE" "COMMAND"
echo "---------------------------------------------------------------------------------------------------------------------------------"
# Read /proc/net/tcp* skipping the first header line
skip_firstline=1
while read -r sl local rem st tx tr retr uid timeout inode extra; do
if [ ${skip_firstline} -eq 1 ]; then
skip_firstline=0
continue
fi
local_readable=$(convert_hex "${local}")
remote_readable=$(convert_hex "${rem}")
state_str=${states[$st]:-"UNKNOWN"}
pid=$(socket2inode ${inode})
username=$(getent passwd ${uid} | cut -d: -f1)
process=$([ -e "/proc/${pid}/cmdline" ] && cat /proc/${pid}/cmdline | tr -d '\0') || ""
printf "%-20s %-20s %-12s %-20s %-6s %-50s\n" "${local_readable}" "${remote_readable}" "${state_str}" "${uid} (${username})" "${inode}" "${process:0:50}"
done
}

# Convert Hex IP (Little Endian) and Hex Port to Human Readable
function convert_hex () {
hex_ip_port=$1
hex_ip=$(echo ${hex_ip_port} | cut -d: -f1)
hex_port=$(echo ${hex_ip_port} | cut -d: -f2)
if [ ${#hex_ip} -eq 8 ]; then
# Extract bytes in reverse order (Little-Endian to Dotted-Decimal)
ip1=$((16#${hex_ip:6:2}))
ip2=$((16#${hex_ip:4:2}))
ip3=$((16#${hex_ip:2:2}))
ip4=$((16#${hex_ip:0:2}))

full_ip4="${ip1}.${ip2}.${ip3}.${ip4}"
else
# Loop through the 32-character string in 8-character blocks (words)
for ((i=0; i<32; i+=8)); do
# Extract the 8-character word
word=${hex_ip:i:8}
# Reverse the 4 bytes (2 characters each) using Bash substring slicing
ip1=${word:6:2}
ip2=${word:4:2}
ip3=${word:2:2}
ip4=${word:0:2}

# Append the reversed bytes as two IPv6 groups (e.g., "aabb:ccdd:")
full_ip6+=":${ip1}${ip2}:${ip3}${ip4}"
done
fi

# Convert port from Hex to Base 10
local port=$((16#$hex_port))

if [ ${#hex_ip} -eq 8 ]; then
echo "${full_ip4}:${port}"
else
echo "${full_ip6:1}:${port}"
fi
}

function socket2inode () {
find /proc/*/fd -type l -ls 2>/dev/null | grep "socket:\[$1\]" | awk '{print $11}' | cut -d/ -f3
}