diff --git a/settings/settings-sshd.env b/settings/settings-sshd.env index c9165c1..539bba5 100644 --- a/settings/settings-sshd.env +++ b/settings/settings-sshd.env @@ -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') @@ -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 +}