diff --git a/Makefile b/Makefile index b398b7c..8f5bbc6 100644 --- a/Makefile +++ b/Makefile @@ -1,21 +1,45 @@ -PLUGIN_FOLDER=~/.kube/plugins/sniff + TCPDUMP_VERSION=4.9.2 +NEW_PLUGIN_SYSTEM_MINIMUM_KUBECTL_VERSION=12 +KUBECTL_MINOR_VERSION=$(shell kubectl version --client=true --short=true -o json | jq .clientVersion.minor) +IS_NEW_PLUGIN_SUBSYSTEM := $(shell [ $(KUBECTL_MINOR_VERSION) -ge $(NEW_PLUGIN_SYSTEM_MINIMUM_KUBECTL_VERSION) ] && echo true) +STATIC_TCPDUMP_NAME=static-tcpdump + +ifeq ($(IS_NEW_PLUGIN_SUBSYSTEM),true) +PLUGIN_FOLDER=/usr/local/bin +PLUGIN_NAME=kubectl-sniff +else +PLUGIN_FOLDER=~/.kube/plugins/sniff +PLUGIN_NAME=ksniff.sh +endif install: install-static-tcpdump install-plugin plugin-folder: - mkdir -p ~/.kube/plugins/sniff + mkdir -p ${PLUGIN_FOLDER} install-plugin: plugin-folder - cp ksniff.sh plugin.yaml ${PLUGIN_FOLDER} - chmod +x ${PLUGIN_FOLDER}/ksniff.sh + if [ "${IS_NEW_PLUGIN_SUBSYSTEM}" != "true" ]; then \ + cp plugin.yaml ${PLUGIN_FOLDER};\ + fi + + cp ksniff.sh ${PLUGIN_FOLDER}/${PLUGIN_NAME} + chmod +x ${PLUGIN_FOLDER}/${PLUGIN_NAME} install-static-tcpdump: plugin-folder static-tcpdump - mv static-tcpdump ${PLUGIN_FOLDER} + mv ${STATIC_TCPDUMP_NAME} ${PLUGIN_FOLDER} static-tcpdump: wget http://www.tcpdump.org/release/tcpdump-${TCPDUMP_VERSION}.tar.gz tar -xvf tcpdump-${TCPDUMP_VERSION}.tar.gz cd tcpdump-${TCPDUMP_VERSION} && CFLAGS=-static ./configure --without-crypto && make - mv tcpdump-${TCPDUMP_VERSION}/tcpdump ./static-tcpdump + mv tcpdump-${TCPDUMP_VERSION}/tcpdump ./${STATIC_TCPDUMP_NAME} rm -rf tcpdump-${TCPDUMP_VERSION} tcpdump-${TCPDUMP_VERSION}.tar.gz + +uninstall: + if [ "${IS_NEW_PLUGIN_SUBSYSTEM}" != "true" ]; then \ + rm -f ${PLUGIN_FOLDER}/plugin.yaml;\ + fi + + rm -f ${PLUGIN_FOLDER}/${STATIC_TCPDUMP_NAME} + rm -f ${PLUGIN_FOLDER}/${PLUGIN_NAME} \ No newline at end of file diff --git a/README.md b/README.md index 7664efd..8e63f9b 100644 --- a/README.md +++ b/README.md @@ -17,26 +17,36 @@ output to your local Wireshark for smooth network debugging experience. ![Demo!](https://i.imgur.com/hWtF9r2.gif) ## Installation + +Requirements: +1. libpcap-dev: for tcpdump compilation (Ubuntu: sudo apt-get install libpcap-dev) +2. jq: for parsing kubectl version + You can easily install the plugin using the Makefile: 1. make install -'make install' will compile a static tcpdump binary and will copy all the required files to your -~/.kube/plugins folder. +'make install' will compile a static tcpdump binary and will copy all the required files to your plugin folder - if you only want to install the plugin files without compiling tcpdump use: +if you only want to install the plugin files without compiling tcpdump use: 1. make install-plugin ### Usage + kubectl < 1.12: kubectl plugin sniff [-n ] [-c ] [-f ] + kubectl >= 1.12: + kubectl sniff [-n ] [-c ] [-f ] + POD_NAME: Required. the name of the kubernetes pod to start capture it's traffic. NAMESPACE_NAME: Optional. Namespace name. used to specify the target namespace to operate on. CONTIANER_NAME: Optional. If omitted, the first container in the pod will be chosen. CAPTURE_FILTER: Optional. specify a specific tcpdump capture filter. If omitted no filter will be used. + + ### Future Work 1. Instead of uploading static tcpdump, use the future support of "kubectl debug" feature diff --git a/ksniff.sh b/ksniff.sh index bb1ea0a..8afb935 100755 --- a/ksniff.sh +++ b/ksniff.sh @@ -1,21 +1,46 @@ #!/usr/bin/env bash +KUBECTL_MINOR_VERSION=$(kubectl version --client=true --short=true -o json | jq .clientVersion.minor) +KUBECTL_MINOR_VERSION="${KUBECTL_MINOR_VERSION%\"}" +KUBECTL_MINOR_VERSION="${KUBECTL_MINOR_VERSION#\"}" +NEW_PLUGIN_SYSTEM_MINIMUM_KUBECTL_VERSION=12 + POD_NAME=${KUBECTL_PLUGINS_LOCAL_FLAG_POD:-$1} CONTAINER_NAME=${KUBECTL_PLUGINS_LOCAL_FLAG_CONTAINER} NAMESPACE_NAME=${KUBECTL_PLUGINS_CURRENT_NAMESPACE} FILTER=${KUBECTL_PLUGINS_LOCAL_FLAG_FILTER} +STATIC_TCPDUMP_NAME=static-tcpdump +STATIC_TCPDUMP_LOCAL_PATH="./" CONTAINER_FLAG="" NAMESPACE_FLAG="" + function usage() { echo "[+] Usage: ./ksniff.sh [-n ] [-c ] [-f ]" exit 1 } if [ -z ${POD_NAME} ]; then - usage + usage fi +shift + +while getopts ":n:c:f:" opt; do + case ${opt} in + n ) + NAMESPACE_NAME=${OPTARG} + ;; + c ) + CONTAINER_NAME=${OPTARG} + ;; + f ) + FILTER=${OPTARG} + ;; + esac +done + + if [ -n "$CONTAINER_NAME" ]; then CONTAINER_FLAG="-c ${CONTAINER_NAME}" fi @@ -24,7 +49,11 @@ if [ -n "$NAMESPACE_NAME" ]; then NAMESPACE_FLAG="-n ${NAMESPACE_NAME}" fi -echo "[+] Sniffing on pod: ${POD_NAME} container: ${CONTAINER_NAME} namespace: ${NAMESPACE_NAME}" +if [ ${KUBECTL_MINOR_VERSION} -ge ${NEW_PLUGIN_SYSTEM_MINIMUM_KUBECTL_VERSION} ]; then + STATIC_TCPDUMP_LOCAL_PATH=/usr/local/bin/ +fi + +echo "[+] Sniffing on pod: '${POD_NAME}' [container: '${CONTAINER_NAME}', namespace: '${NAMESPACE_NAME}', filter: '${FILTER}']" echo "[+] Verifying pod status" kubectl get pod ${POD_NAME} ${NAMESPACE_FLAG} @@ -34,14 +63,20 @@ if [[ $? -ne 0 ]]; then fi echo "[+] checking if tcpdump already exist" -kubectl exec ${POD_NAME} ${CONTAINER_FLAG} ${NAMESPACE_FLAG} -- ls -alt /static-tcpdump +kubectl exec ${POD_NAME} ${CONTAINER_FLAG} ${NAMESPACE_FLAG} -- ls -alt /${STATIC_TCPDUMP_NAME} if [[ $? -ne 0 ]]; then echo "[+] couldn't find static tcpdump binary, uploading static tcpdump to container" - kubectl cp ./static-tcpdump ${POD_NAME}:/static-tcpdump ${CONTAINER_FLAG} ${NAMESPACE_FLAG} - kubectl exec ${POD_NAME} ${CONTAINER_FLAG} ${NAMESPACE_FLAG} -- chmod +x /static-tcpdump + + if [ ! -f ${STATIC_TCPDUMP_LOCAL_PATH}${STATIC_TCPDUMP_NAME} ]; then + echo "[-] static tcpdump was not found in path! please install it and make sure it's located on the same directory as ksniff" + exit 1 + fi + + kubectl cp ${STATIC_TCPDUMP_LOCAL_PATH}${STATIC_TCPDUMP_NAME} ${POD_NAME}:/${STATIC_TCPDUMP_NAME} ${CONTAINER_FLAG} ${NAMESPACE_FLAG} + kubectl exec ${POD_NAME} ${CONTAINER_FLAG} ${NAMESPACE_FLAG} -- chmod +x /${STATIC_TCPDUMP_NAME} else echo "[+] static tcpdump is already installed on container!" fi echo "[+] Starting remote sniffing!" -kubectl exec ${POD_NAME} ${CONTAINER_FLAG} ${NAMESPACE_FLAG} -- /static-tcpdump -U -w - ${FILTER} | wireshark -k -i - +kubectl exec ${POD_NAME} ${CONTAINER_FLAG} ${NAMESPACE_FLAG} -- /${STATIC_TCPDUMP_NAME} -U -w - ${FILTER} | wireshark -k -i -