Skip to content
Open
Show file tree
Hide file tree
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
10 changes: 9 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,16 @@ FROM --platform=$BUILDPLATFORM alpine as user
RUN adduser -S -u 10000 lantern

FROM alpine
Copy link

Copilot AI Jul 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding a comment explaining why iptables is required in this image to help future maintainers understand this dependency.

Suggested change
FROM alpine
FROM alpine
# iptables is required for managing network traffic and firewall rules in the application.

Copilot uses AI. Check for mistakes.
RUN apk add --no-cache iptables su-exec

COPY --from=user /etc/passwd /etc/passwd
COPY --from=builder /usr/local/bin/http-proxy /usr/local/bin/http-proxy

USER lantern
COPY servermasq.sh /servermasq.sh
RUN chmod +x /servermasq.sh

# Run as root because iptables in the servermasq.sh script needs root privileges
# the script itself will switch to the lantern user before executing the http-proxy binary
USER root
ENTRYPOINT ["/servermasq.sh"]
CMD ["/usr/local/bin/http-proxy"]
49 changes: 49 additions & 0 deletions servermasq.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#!/bin/sh
set -e

echo "[+] Setting up LANTERN_SERVERMASQ iptables chain..."

PROXY_ADDR=$(hostname -i | awk '{print $1}')

if [ -z "$PROXY_ADDR" ] || [ -z "$PROXY_PORT" ] || [ -z "$MASQ_ADDR" ]; then
echo "[~] Required environment variables not set, skipping iptables setup"
exec "$@"
fi

# The iptables rules can be explained as follows:
# 1. Create a new chain called LANTERN_SERVERMASQ.
# 2. Add a rule to the LANTERN_SERVERMASQ chain that matches packets destined for the proxy address
# (PROXY_ADDR) that are not destined for the proxy port (PROXY_PORT), and redirects them to the MASQ_ADDR.
# It is important to understand the context in which this docker container is running and this determines the
# value of PROXY_ADDR. PROXY_ADDR is the container's internal IP address. See flow of traffic below:

# [ External Client (public internet) ]
# |
# v
# [ Public IP of cloud provider ]
# |
# (NAT to private IP)
# |
# v
# [ VM Private IP (e.g., 10.52.x.x) ]
# |
# (Host port → Container port binding)
# |
# (Docker NAT to container IP)
# |
# v
# [ Docker Container IP (e.g., 172.17.x.x) ]

# 3. Add a rule to the PREROUTING chain that matches packets destined for the proxy address (PROXY_ADDR)
# and redirects them to the LANTERN_SERVERMASQ chain.
# 4. Add a rule to the POSTROUTING chain that matches packets destined for the MASQ_ADDR and masquerades them in order for responses to be sent back correctly to container.

iptables -t nat -N LANTERN_SERVERMASQ 2>/dev/null || true
iptables -t nat -F LANTERN_SERVERMASQ 2>/dev/null || true

iptables -t nat -A LANTERN_SERVERMASQ -d "$PROXY_ADDR" -p tcp ! --dport "$PROXY_PORT" -j DNAT --to-destination "$MASQ_ADDR"
iptables -t nat -A PREROUTING -d "$PROXY_ADDR" -j LANTERN_SERVERMASQ
iptables -t nat -A POSTROUTING -d "$MASQ_ADDR" -j MASQUERADE

echo "[+] LANTERN_SERVERMASQ setup complete: $@"
exec su-exec lantern "$@"
Loading