The issue
I'm attempting to run an nmap scan from a gcp Cloud Run Service, but the scan fails due to a routing error. Specifically, when I attempt to scan scanme.nmap.org
, I received the following logs:
Warning: Hostname scanme.nmap.org resolves to 2 IPs. Using 45.33.32.156.
setup_target: failed to determine route to scanme.nmap.org (45.33.32.156)
Read data files from: /usr/bin/../share/nmap
Nmap done: 0 IP addresses (0 hosts up) scanned in 0.14 seconds
Raw packets sent: 0 (0B) | Rcvd: 0 (0B)
WARNING: No targets were specified, so 0 hosts scanned.
What's been tried
I've tried to ping scanme.nmap.org
and curl it, both of which succeed, which suggests something is wrong in Cloud run related to nmap in particular.
I've looked around at similar issues and found that this could be due to routing issues, so I checked the nmap routing options with /usr/bin/nmap --iflist
, which gave the following output:
************************INTERFACES************************
DEV (SHORT) IP/MASK TYPE UP MTU MAC
lo (lo) (none)/8 loopback up 65522
...etc
eth2 (eth2) (none)/32 other up 1280
eth2 (eth2) 169.254.8.1/32 other up 1280
eth2 (eth2) fddf:3978:feb1:d745::c001/128 other up 1280
**************************ROUTES**************************
169.254.1.1/32 eth0 0
0.0.0.0/0 eth2 0
I then attempted to force nmap to use eth2 via the command /usr/bin/nmap -e eth2 -sn scanme.nmap.org
which should be the correct interface for the ip, and got the error Failed to convert source address to presentation format!?! Error: Address family not supported by protocol
.
The only tangentially related question I found had two comments where someone had the same issue, but no posted resolution.
Minimum reproducible exmple
The minimum code to reproduce this is as follows:
main.py
import os
from flask import Flask
from flask import request
@app.route("/", methods=['POST'])
def hello_world():
os.system("/usr/bin/nmap -vvvvv -sT scanme.nmap.org")
requirements.txt
Flask==2.1.0
gunicorn==20.1.0
Dockerfile
# Use the official lightweight Python image.
# https://hub.docker.com/_/python
FROM python:3.10-slim
# Allow statements and log messages to immediately appear in the Knative logs
ENV PYTHONUNBUFFERED True
# Copy local code to the container image.
ENV APP_HOME /app
WORKDIR $APP_HOME
COPY . ./
RUN apt-get update && \
apt-get install -qy nmap curl wget && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
# Install production dependencies.
RUN pip install --no-cache-dir -r requirements.txt
# Run the web service on container startup. Here we use the gunicorn
# webserver, with one worker process and 8 threads.
# For environments with multiple CPU cores, increase the number of workers
# to be equal to the cores available.
# Timeout is set to 0 to disable the timeouts of the workers to allow Cloud Run to handle instance scaling.
CMD exec gunicorn --bind :$PORT --workers 1 --threads 8 --timeout 0 main:app
Deploy command:
gcloud builds submit --tag gcr.io/{project-id}/example-service . && gcloud run deploy example-service --image gcr.io/{project-id}/example-service --region us-central1 --project {project-id}