Skip to content

Commit 32337a7

Browse files
author
Alex Fraser
committed
Added HTTPS support
A root SSL certificate is generated when the server starts up; this is used to man-in-the-middle HTTPS requests. The client will still be able to tell that their connection is compromised, since by default they won't trust the new CA.
1 parent 47add76 commit 32337a7

File tree

6 files changed

+133
-45
lines changed

6 files changed

+133
-45
lines changed

Dockerfile

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,46 @@
1-
FROM silarsis/base
2-
MAINTAINER Kevin Littlejohn <kevin@littlejohn.id.au>
3-
RUN apt-get -yq update
1+
FROM ubuntu:14.04
2+
3+
MAINTAINER Alex Fraser <alex@vpac-innovations.com.au>
4+
5+
# Run a caching proxy on the host and bind a port to APT_PROXY_PORT to cache
6+
# apt requests. Build with `docker build --build-arg APT_PROXY_PORT=[X] [...]`.
7+
WORKDIR /root
8+
ARG APT_PROXY_PORT=
9+
COPY detect-apt-proxy.sh /root/
10+
RUN export DEBIAN_FRONTEND=noninteractive TERM=linux \
11+
&& ./detect-apt-proxy.sh ${APT_PROXY_PORT} no \
12+
&& apt-get update \
13+
&& apt-get install -y --no-install-recommends \
14+
build-essential \
15+
curl \
16+
dpkg-dev \
17+
iptables \
18+
libssl-dev \
19+
patch \
20+
squid-langpack \
21+
ssl-cert \
22+
&& apt-get source -y squid3 squid-langpack \
23+
&& apt-get build-dep -y squid3 squid-langpack
24+
# rm -rf /var/lib/apt/lists/* \
25+
# /etc/apt/apt.conf.d/30proxy \
26+
27+
# It's silly, but run dpkg-buildpackage again if it fails the first time. This
28+
# is needed because sometimes the `configure` script is busy when building in
29+
# Docker after autoconf sets its mode +x.
30+
COPY squid3.patch /root/
31+
RUN cd squid3-3.?.? \
32+
&& patch -p1 < /root/squid3.patch \
33+
&& export NUM_PROCS=`grep -c ^processor /proc/cpuinfo` \
34+
&& (dpkg-buildpackage -b -j${NUM_PROCS} || dpkg-buildpackage -b -j${NUM_PROCS})
35+
RUN dpkg -i \
36+
squid3-common_3.?.?-?ubuntu?.?_all.deb \
37+
squid3_3.?.?-?ubuntu?.?_*.deb \
38+
&& mkdir -p /etc/squid3/ssl_cert
439

5-
RUN apt-get -yq install squid iptables
640
ADD squid.conf /etc/squid3/squid.conf
741
ADD start_squid.sh /usr/local/bin/start_squid.sh
842

9-
EXPOSE 3128
43+
VOLUME /var/spool/squid3
44+
EXPOSE 3128 3129
1045

1146
CMD ["/usr/local/bin/start_squid.sh"]

detect-apt-proxy.sh

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!/bin/bash
2+
3+
# If the host is running a web proxy, use it for apt.
4+
# Adapted from https://gist.github.com/dergachev/8441335
5+
6+
APT_PROXY_PORT=$1
7+
PROXY_LAUNCHPAD=${2:-no}
8+
9+
HOST_IP=$(route -n | awk '/^0.0.0.0/ {print $2}')
10+
nc -z "$HOST_IP" ${APT_PROXY_PORT}
11+
12+
if [ $? -eq 0 ]; then
13+
echo "Acquire::http::Proxy \"http://$HOST_IP:$APT_PROXY_PORT\";" >> /etc/apt/apt.conf.d/30proxy
14+
if [ "$PROXY_LAUNCHPAD" = yes ]; then
15+
echo "Acquire::http::Proxy::ppa.launchpad.net DIRECT;" >> /etc/apt/apt.conf.d/30proxy
16+
fi
17+
echo "Using host's apt proxy"
18+
else
19+
echo "No apt proxy detected on Docker host"
20+
fi

run.sh

Lines changed: 21 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,13 @@
33
# Script to maintain ip rules on the host when starting up a transparent
44
# proxy server for docker.
55

6-
CACHEDIR="/tmp/squid3" # Change this to place the cache somewhere else
6+
CACHEDIR=${CACHEDIR:-/tmp/squid3}
7+
CONTAINER_NAME=${CONTAINER_NAME:-docker-proxy}
78

89
set -e
910

10-
# Guard for my own scripts
11-
# Note, if you're running this script direct, it will rebuild if it can't see
12-
# the image.
13-
[ -z ${RUNNING_DRUN} ] && {
14-
RUN_DOCKER="docker run"
15-
CONTAINER_NAME='docker-proxy'
16-
docker images | grep "^${CONTAINER_NAME} " >/dev/null || docker build -q --rm -t ${CONTAINER_NAME} "$(dirname $0)"
17-
}
11+
sudo docker images | grep -q "^${CONTAINER_NAME} " \
12+
|| (echo "Build ${CONTAINER_NAME} image first" && exit 1)
1813

1914
start_routing () {
2015
# Add a new route table that routes everything marked through the new container
@@ -28,13 +23,15 @@ start_routing () {
2823
sudo ln -s /usr/local/etc/iproute2/rt_tables /etc/iproute2/rt_tables
2924
fi
3025
fi
31-
([ -e /etc/iproute2/rt_tables ] && grep TRANSPROXY /etc/iproute2/rt_tables >/dev/null) || \
32-
sudo sh -c "echo '1 TRANSPROXY' >> /etc/iproute2/rt_tables"
33-
ip rule show | grep TRANSPROXY >/dev/null || \
34-
sudo ip rule add from all fwmark 0x1 lookup TRANSPROXY
26+
([ -e /etc/iproute2/rt_tables ] && grep -q TRANSPROXY /etc/iproute2/rt_tables) \
27+
|| sudo sh -c "echo '1 TRANSPROXY' >> /etc/iproute2/rt_tables"
28+
ip rule show | grep -q TRANSPROXY \
29+
|| sudo ip rule add from all fwmark 0x1 lookup TRANSPROXY
3530
sudo ip route add default via "${IPADDR}" dev docker0 table TRANSPROXY
36-
# Mark packets to port 80 external, so they route through the new route table
31+
# Mark packets to port 80 and 443 external, so they route through the new
32+
# route table
3733
sudo iptables -t mangle -I PREROUTING -p tcp --dport 80 \! -s "${IPADDR}" -i docker0 -j MARK --set-mark 1
34+
sudo iptables -t mangle -I PREROUTING -p tcp --dport 443 \! -s "${IPADDR}" -i docker0 -j MARK --set-mark 1
3835
# Exemption rule to stop docker from masquerading traffic routed to the
3936
# transparent proxy
4037
sudo iptables -t nat -I POSTROUTING -o docker0 -s 172.17.0.0/16 -j ACCEPT
@@ -44,22 +41,19 @@ stop_routing () {
4441
# Remove the appropriate rules - that is, those that mention the IP Address.
4542
set +e
4643
[ "x$IPADDR" != "x" ] && {
47-
ip route show table TRANSPROXY | grep default >/dev/null && \
48-
sudo ip route del default table TRANSPROXY
49-
sudo iptables -t mangle -L PREROUTING -n | grep 'tcp dpt:80 MARK set 0x1' >/dev/null && \
50-
sudo iptables -t mangle -D PREROUTING -p tcp --dport 80 \! -s "${IPADDR}" -i docker0 -j MARK --set-mark 1
44+
ip route show table TRANSPROXY | grep -q default \
45+
&& sudo ip route del default table TRANSPROXY
46+
sudo iptables -t mangle -L PREROUTING -n | grep -q 'tcp dpt:80 MARK set 0x1' \
47+
&& sudo iptables -t mangle -D PREROUTING -p tcp --dport 80 \! -s "${IPADDR}" -i docker0 -j MARK --set-mark 1 \
48+
&& sudo iptables -t mangle -D PREROUTING -p tcp --dport 443 \! -s "${IPADDR}" -i docker0 -j MARK --set-mark 1 \
5149
sudo iptables -t nat -D POSTROUTING -o docker0 -s 172.17.0.0/16 -j ACCEPT 2>/dev/null
5250
}
5351
set -e
5452
}
5553

5654
stop () {
57-
# Ideally we'd leave the container around and re-use it, but I really
58-
# need a nice way to query for a named container first. Doesn't cost much
59-
# to create a new container anyway, especially given the cache volume is mapped.
6055
set +e
61-
docker kill ${CONTAINER_NAME} >/dev/null 2>&1
62-
docker rm ${CONTAINER_NAME} >/dev/null 2>&1
56+
sudo docker rm -f ${CONTAINER_NAME} >/dev/null 2>&1
6357
set -e
6458
stop_routing
6559
}
@@ -85,18 +79,17 @@ run () {
8579
# Because we're named, make sure the container doesn't already exist
8680
stop
8781
# Run and find the IP for the running container
88-
CID=$(${RUN_DOCKER} --privileged -d -v "${CACHEDIR}":/var/spool/squid3 --name ${CONTAINER_NAME} ${CONTAINER_NAME})
89-
IPADDR=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' ${CID})
82+
CID=$(sudo docker run --privileged -d -v "${CACHEDIR}":/var/spool/squid3 --name ${CONTAINER_NAME} ${CONTAINER_NAME})
83+
IPADDR=$(sudo docker inspect --format '{{ .NetworkSettings.IPAddress }}' ${CID})
9084
start_routing
9185
# Run at console, kill cleanly if ctrl-c is hit
9286
trap interrupted INT
9387
trap terminated TERM
9488
echo 'Now entering wait, please hit "ctrl-c" to kill proxy and undo routing'
95-
docker logs -f "${CID}"
89+
sudo docker logs -f "${CID}"
9690
echo 'Squid exited unexpectedly, cleaning up...'
9791
stop
9892
}
9993

100-
# Guard so I can include this script into my own scripts
101-
[ -z ${RUNNING_DRUN} ] && run
94+
run
10295
echo

squid.conf

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,27 @@ acl Safe_ports port 488 # gss-http
1010
acl Safe_ports port 591 # filemaker
1111
acl Safe_ports port 777 # multiling http
1212
acl CONNECT method CONNECT
13+
1314
http_access deny !Safe_ports
1415
http_access deny CONNECT !SSL_ports
1516
http_access allow localhost manager
1617
http_access deny manager
1718
http_access allow localhost
1819
http_access allow all
1920
#http_access deny all
20-
http_port 3128 transparent
21+
22+
http_port 3128 intercept
23+
https_port 3129 cert=/etc/squid3/ssl_cert/myCA.pem generate-host-certificates=on intercept ssl-bump
24+
2125
maximum_object_size 512 MB
2226
cache_dir ufs /var/spool/squid3 2024 2 8
2327
cache_mem 200 MB
2428
maximum_object_size_in_memory 100 MB
2529
cache_replacement_policy heap LFUDA
30+
2631
refresh_pattern Packages\.bz2$ 0 20% 4320 refresh-ims
2732
refresh_pattern Sources\.bz2$ 0 20% 4320 refresh-ims
2833
refresh_pattern Release\.gpg$ 0 20% 4320 refresh-ims
2934
refresh_pattern Release$ 0 20% 4320 refresh-ims
30-
refresh_pattern -i .(udeb|tar.gz|deb|rpm|exe|zip|tar|tgz|bz2|ram|rar|bin)$ 129600 100% 129600 override-expire ignore-no-cache ignore-no-store
35+
refresh_pattern -i .(udeb|tar.gz|deb|rpm|exe|zip|tar|tgz|bz2|ram|rar|bin|jar)$ 129600 100% 129600 override-expire ignore-no-cache ignore-no-store
3136
refresh_pattern . 0 20% 4320

squid3.patch

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
--- a/debian/rules 2014-02-18 03:13:28.000000000 +0000
2+
+++ b/debian/rules 2016-04-04 02:03:23.732296279 +0000
3+
@@ -41,8 +41,10 @@
4+
--enable-icmp \
5+
--enable-zph-qos \
6+
--enable-ecap \
7+
+ --enable-ssl \
8+
--disable-translation \
9+
--with-swapdir=/var/spool/squid3 \
10+
+ --with-open-ssl=/etc/ssl/openssl.cnf \
11+
--with-logdir=/var/log/squid3 \
12+
--with-pidfile=/var/run/squid3.pid \
13+
--with-filedescriptors=65536 \

start_squid.sh

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,38 @@
11
#!/bin/bash
22

3-
# Setup the NAT rule that enables transparent proxying
4-
IPADDR=$(/sbin/ip -o -f inet addr show eth0 | awk '{ sub(/\/.+/,"",$4); print $4 }')
5-
iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination ${IPADDR}:3128
3+
function gen-cert() {
4+
cd /etc/squid3/ssl_cert
5+
openssl req -new -newkey rsa:2048 -sha256 -days 365 -nodes -x509 \
6+
-keyout myCA.pem -out myCA.pem \
7+
-subj '/CN=squid-ssl/O=NULL/C=AU'
8+
chmod 600 myCA.pem
9+
openssl x509 -in myCA.pem -outform DER -out myCA.der
10+
chown proxy.proxy myCA.pem
11+
return $?
12+
}
613

7-
# Make sure our cache is setup
8-
chown proxy.proxy /var/spool/squid3
9-
[ -e /var/spool/squid3/swap.state ] || squid3 -z 2>/dev/null
14+
function start-routing() {
15+
# Setup the NAT rule that enables transparent proxying
16+
IPADDR=$(/sbin/ip -o -f inet addr show eth0 | awk '{ sub(/\/.+/,"",$4); print $4 }')
17+
iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination ${IPADDR}:3128
18+
return $?
19+
}
20+
21+
function init-cache() {
22+
# Make sure our cache is setup
23+
touch /var/log/squid3/access.log /var/log/squid3/cache.log
24+
chown proxy.proxy -R /var/spool/squid3 /var/log/squid3
25+
[ -e /var/spool/squid3/swap.state ] || squid3 -z 2>/dev/null
26+
}
27+
28+
gen-cert || exit 1
29+
start-routing || exit 1
30+
init-cache
31+
32+
echo starting server
1033

1134
# Run squid and tail the logs
1235
squid3
13-
while true; do
14-
[ -e /var/log/squid3/access.log ] && tail -f /var/log/squid3/access.log
15-
sleep 1
16-
done
36+
sleep 0.5
37+
ps aux
38+
tail -f /var/log/squid3/access.log /var/log/squid3/cache.log

0 commit comments

Comments
 (0)