Skip to main content
Glama
entrypoint.sh9.38 kB
#!/bin/sh set -e MITM_PROXY_PID="" APP_PID="" is_container_privileged() { num_caps=$(capsh --print | grep "Current:" | tr ',' '\n' | grep -c "cap_") num_caps_op2=$(capsh --print | grep "Bounding set =" | tr ',' '\n' | grep -c "cap_") if [ "$num_caps" -gt 36 ] || [ "$num_caps_op2" -gt 36 ]; then return 0 else return 1 fi } is_cap_admin_enabled() { cap_admin=$(capsh --print | grep "Current:" | grep -c "cap_net_admin") cap_admin_op2=$(capsh --print | grep "Bounding set =" | grep -c "cap_net_admin") if [ "$cap_admin" -gt 0 ] || [ "$cap_admin_op2" -gt 0 ]; then return 0 else return 1 fi } cleanup() { echo "Cleanup called..." if [ -n "$APP_PID" ]; then echo "Attempting to stop application (PID $APP_PID)..." # Send TERM, then wait a bit, then KILL if still alive kill "$APP_PID" >/dev/null 2>&1 sleep 0.5 ( kill -0 "$APP_PID" >/dev/null 2>&1 && kill -9 "$APP_PID" >/dev/null 2>&1 ) || true wait "$APP_PID" 2>/dev/null || true echo "Application stopped." APP_PID="" fi if [ -n "$MITM_PROXY_PID" ]; then echo "Attempting to stop mitmproxy (PID $MITM_PROXY_PID)..." kill "$MITM_PROXY_PID" >/dev/null 2>&1 sleep 0.5 ( kill -0 "$MITM_PROXY_PID" >/dev/null 2>&1 && kill -9 "$MITM_PROXY_PID" >/dev/null 2>&1 ) || true wait "$MITM_PROXY_PID" 2>/dev/null || true echo "mitmproxy stopped." MITM_PROXY_PID="" fi echo "Cleanup finished." } resolve_host_ips() { host="$1" if [ -z "$host" ]; then echo "Usage: resolve_host_ips <hostname>" >&2 return 1 fi nslookup "$host" 2>/dev/null \ | awk '/^Address: / { print $2 }' \ | grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}' \ || echo "" # Output empty string if no IPv4 found to prevent issues with loops } wait_for_docker() { if ! pgrep -f "dockerd" > /dev/null 2>&1; then if [ -f /var/run/docker.pid ]; then rm -f /var/run/docker.pid fi dockerd > /var/log/dockerd.log 2>&1 & fi WAIT_TIMEOUT=5 WAIT_INTERVAL=2 elapsed_time=0 while ! docker info > /dev/null 2>&1; do if [ "$elapsed_time" -ge "$WAIT_TIMEOUT" ]; then echo "ENTRYPOINT ERROR: Docker daemon did not become ready within $WAIT_TIMEOUT seconds." echo "Dockerd logs:" tail -n 50 /var/log/dockerd.log || echo "(no dockerd log found or readable)" return 1 fi sleep "$WAIT_INTERVAL" elapsed_time=$((elapsed_time + WAIT_INTERVAL)) done return 0 } init_interception() { echo "ENTRYPOINT: Initializing traffic interception..." # --- Configuration Variables --- # mitmproxy settings MITM_PROXY_LISTEN_HOST="${MITM_PROXY_LISTEN_HOST:-0.0.0.0}" MITM_PROXY_LISTEN_PORT="${MITM_PROXY_LISTEN_PORT:-8081}" MITM_PROXY_ADDON_SCRIPT="/opt/lunar_selective_addon.py" MITM_PROXY_CONF_DIR_BASE="${MITM_PROXY_CONF_DIR_BASE:-/home/${INTERCEPTION_USER}/.lunar}" MITM_PROXY_CONF_DIR="${MITM_PROXY_CONF_DIR_BASE}/mitmproxy_conf" export MITM_PROXY_CA_CERT_PATH="${MITM_PROXY_CONF_DIR}/mitmproxy-ca-cert.pem" MITM_PROXY_LOG_FILE="/var/log/${LUNAR_USER:-lunar}/lunar_interception.log" # iptables and networking settings IPSET_NAME_V4="lunar_exclude_ipv4" if is_container_privileged; then echo 1 > /proc/sys/net/ipv4/ip_forward fi if ! su-exec "${INTERCEPTION_USER}" test -f "${MITM_PROXY_CONF_DIR}"; then su-exec "${INTERCEPTION_USER}" \ timeout 10s mitmdump --quiet \ --set "confdir=${MITM_PROXY_CONF_DIR}" \ --listen-host 127.0.0.1 --listen-port 9999 & # Dummy port for CA gen MITMDUMP_GEN_PID=$! for _ in $(seq 1 20); do if su-exec "${INTERCEPTION_USER}" test -f "$MITM_PROXY_CA_CERT_PATH"; then break fi sleep 0.5 done kill $MITMDUMP_GEN_PID >/dev/null 2>&1 || true; sleep 0.5 ( kill -0 $MITMDUMP_GEN_PID >/dev/null 2>&1 && kill -9 $MITMDUMP_GEN_PID >/dev/null 2>&1 ) || true wait $MITMDUMP_GEN_PID 2>/dev/null || true if ! su-exec "${INTERCEPTION_USER}" test -f "$MITM_PROXY_CA_CERT_PATH"; then echo "CRITICAL ERROR: Failed to generate lunar CA as ${INTERCEPTION_USER} at ${MITM_PROXY_CA_CERT_PATH}." exit 1 fi fi cp "$MITM_PROXY_CA_CERT_PATH" "/mitmproxy-ca-cert.pem" chmod +x "/mitmproxy-ca-cert.pem" if command -v update-ca-certificates > /dev/null; then cp "$MITM_PROXY_CA_CERT_PATH" "/usr/local/share/ca-certificates/proxy_lunar.crt" update-ca-certificates elif command -v update-ca-trust > /dev/null; then cp "$MITM_PROXY_CA_CERT_PATH" "/etc/pki/ca-trust/source/anchors/proxy_lunar.crt" update-ca-trust extract else echo "WARNING: Could not update system CA certificates automatically." fi if [ -n "$NODE_EXTRA_CA_CERTS" ]; then export NODE_EXTRA_CA_CERTS="$NODE_EXTRA_CA_CERTS:$MITM_PROXY_CA_CERT_PATH" else export NODE_EXTRA_CA_CERTS="$MITM_PROXY_CA_CERT_PATH" fi if ipset list -n | grep -qx "$IPSET_NAME_V4"; then echo "Flushing ipset: $IPSET_NAME_V4" ipset flush "$IPSET_NAME_V4" else if ! ipset create "${IPSET_NAME_V4}" hash:net family inet; then echo " CRITICAL ERROR: Failed to create ipset '${IPSET_NAME_V4}'. Exiting." exit 1 fi fi # Add user-defined EXCLUDED_DESTINATIONS if [ -n "$EXCLUDED_DESTINATIONS" ]; then OLD_IFS_LOOP="$IFS" IFS=',' for dest_item_raw in $EXCLUDED_DESTINATIONS; do dest_item=$(echo "$dest_item_raw" | awk '{$1=$1};1') if [ -z "$dest_item" ]; then continue; fi if echo "$dest_item" | grep -Eq '^([0-9]{1,3}\.){3}[0-9]{1,3}(\/[0-9]{1,2})?$'; then if ! ipset -q add "${IPSET_NAME_V4}" "$dest_item"; then continue; fi else resolve_host_ips "$dest_item" | while IFS= read -r ip_line || [ -n "$ip_line" ]; do ip=$(echo "$ip_line" | awk '{$1=$1};1') if [ -n "$ip" ]; then if ! ipset -q add "${IPSET_NAME_V4}" "$ip"; then continue; fi fi done fi done IFS="$OLD_IFS_LOOP" fi # --- IPTables Rules --- iptables -t nat -F PREROUTING iptables -t nat -A PREROUTING -m set --match-set "$IPSET_NAME_V4" dst -j RETURN iptables -t nat -A OUTPUT -o lo -j RETURN iptables -t nat -A OUTPUT -m set --match-set "$IPSET_NAME_V4" dst -j RETURN iptables -t nat -A OUTPUT -p tcp -m owner --uid-owner "$(id -u "${INTERCEPTION_USER}")" -j RETURN iptables -t nat -A OUTPUT -p tcp -j REDIRECT --to-port "$MITM_PROXY_LISTEN_PORT" iptables -t nat -A POSTROUTING -j MASQUERADE mkdir -p "$(dirname "$MITM_PROXY_LOG_FILE")" unset HTTP_PROXY HTTPS_PROXY http_proxy https_proxy NO_PROXY no_proxy su-exec "${INTERCEPTION_USER}" \ sh -c "cd /home/${INTERCEPTION_USER} && exec mitmdump \ --showhost \ -s \"$MITM_PROXY_ADDON_SCRIPT\" \ --set \"confdir=${MITM_PROXY_CONF_DIR}\" \ --set block_global=false \ --set \"listen_host=${MITM_PROXY_LISTEN_HOST}\" \ --set \"listen_port=${MITM_PROXY_LISTEN_PORT}\" \ " > "$MITM_PROXY_LOG_FILE" 2>&1 & MITM_PROXY_PID=$! if ! ps -p $MITM_PROXY_PID > /dev/null; then echo "CRITICAL ERROR: mitmproxy failed to start. Check $MITM_PROXY_LOG_FILE." cat "$MITM_PROXY_LOG_FILE" exit 1 fi sleep 1 } # --- Trap signals for graceful shutdown --- # Ensure cleanup runs on exit, regardless of how the script exits. # Note: 'exit' trap is bash-specific, using TERM/INT/QUIT is more portable for sh. trap 'echo "ENTRYPOINT: Signal INT received, cleaning up..."; cleanup; exit 130' INT trap 'echo "ENTRYPOINT: Signal TERM received, cleaning up..."; cleanup; exit 143' TERM trap 'echo "ENTRYPOINT: Signal QUIT received, cleaning up..."; cleanup; exit 131' QUIT export INTERCEPTION_ENABLED="false" if is_container_privileged; then wait_for_docker export DIND_ENABLED="true" else export DIND_ENABLED="false" fi if [ -n "$LUNAR_GATEWAY_URL" ]; then if [[ "$LUNAR_GATEWAY_URL" =~ ^https?:// ]]; then if is_cap_admin_enabled; then init_interception export INTERCEPTION_ENABLED="true" else echo "ENTRYPOINT Warning: Insufficient capabilities for traffic interception. Skipping traffic interception." echo " Please run the container with --cap-add=NET_ADMIN (or the equivalent for your orchestrator)." fi else echo "ENTRYPOINT Warning: LUNAR_GATEWAY_URL must start with http:// or https://. Skipping traffic interception." fi else echo "ENTRYPOINT: LUNAR_GATEWAY_URL not set. Skipping traffic interception." fi exec "$@" & # Run the main app in the background APP_PID=$! wait $APP_PID APP_EXIT_CODE=$? echo "Application (PID $APP_PID) exited with code $APP_EXIT_CODE." if [ -n "$LUNAR_GATEWAY_URL" ]; then echo "Application finished, performing final cleanup..." cleanup fi exit $APP_EXIT_CODE

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/TheLunarCompany/lunar'

If you have feedback or need assistance with the MCP directory API, please join our Discord server