-
Notifications
You must be signed in to change notification settings - Fork 76
/
entrypoint-router.sh
executable file
·149 lines (119 loc) · 4.93 KB
/
entrypoint-router.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#!/usr/bin/env sh
set -Eeo pipefail
if [ "${1:0:1}" = '-' ]; then
set -- zerotier-one "$@"
fi
# useful paths
CONFIG_DIR="/var/lib/zerotier-one"
NETWORKS_DIR="${CONFIG_DIR}/networks.d"
# set up network auto-join if (a) the networks directory does not exist
# and (b) the ZEROTIER_ONE_NETWORK_IDS environment variable is non-null.
if [ ! -d "${NETWORKS_DIR}" -a -n "${ZEROTIER_ONE_NETWORK_IDS}" ] ; then
echo "Assuming container first run."
mkdir -p "${NETWORKS_DIR}"
for NETWORK_ID in ${ZEROTIER_ONE_NETWORK_IDS} ; do
echo "Configuring auto-join of network ID: ${NETWORK_ID}"
touch "${NETWORKS_DIR}/${NETWORK_ID}.conf"
echo "You will need to authorize this host at:"
echo " https://my.zerotier.com/network/${NETWORK_ID}"
done
fi
# make sure permissions are always as expected (self-repair)
PUID="${PUID:-"999"}"
PGID="${PGID:-"994"}"
if [ "$(id -u)" = '0' -a -d "${CONFIG_DIR}" ]; then
chown -Rc "${PUID}:${PGID}" "${CONFIG_DIR}"
fi
# is routing enabled?
if [ $(sysctl -n net.ipv4.ip_forward) -ne 1 ] ; then
# no! there is no point in setting up rules or termination handler
echo "$(date) - IPv4 forwarding not enabled - launching ZeroTier-One in non-routing mode"
# just exec the client (this script ends here)
exec "$@"
fi
echo "$(date) - launching ZeroTier-One in routing mode"
# use an appropriate default for a local physical interface
# (using eth0 maintains backwards compatibility)
PHY_IFACES="${ZEROTIER_ONE_LOCAL_PHYS:-"eth0"}"
# default to iptables (maintains backwards compatibility)
IPTABLES_CMD=iptables-legacy
# but support an override to use iptables-nft
[ "${ZEROTIER_ONE_USE_IPTABLES_NFT}" = "true" ] && IPTABLES_CMD=iptables-nft
# the default forwarding mode is inbound (backwards compatible)
GATEWAY_MODE="${ZEROTIER_ONE_GATEWAY_MODE:-"inbound"}"
# the wildcard for the local zerotier interface is
ZT_IFACE="zt+"
# function to add and remove the requisite rules
# - $1 is either "A" (add) or "D" (delete)
# - $2 is comment
update_iptables() {
case "${GATEWAY_MODE}" in
"inbound" )
echo "$2 ${IPTABLES_CMD} rules for inbound traffic (ZeroTier to local interfaces ${PHY_IFACES})"
for PHY_IFACE in ${PHY_IFACES} ; do
${IPTABLES_CMD} -t nat -${1} POSTROUTING -o ${PHY_IFACE} -j MASQUERADE
${IPTABLES_CMD} -${1} FORWARD -i ${PHY_IFACE} -o ${ZT_IFACE} -m state --state RELATED,ESTABLISHED -j ACCEPT
${IPTABLES_CMD} -${1} FORWARD -i ${ZT_IFACE} -o ${PHY_IFACE} -j ACCEPT
${IPTABLES_CMD} -${1} FORWARD -i ${PHY_IFACE} -o ${ZT_IFACE} -j DROP
done
;;
"outbound" )
echo "$2 ${IPTABLES_CMD} rules for outbound traffic (local interfaces ${PHY_IFACES} to ZeroTier)"
${IPTABLES_CMD} -t nat -${1} POSTROUTING -o ${ZT_IFACE} -j MASQUERADE
for PHY_IFACE in ${PHY_IFACES} ; do
${IPTABLES_CMD} -${1} FORWARD -i ${ZT_IFACE} -o ${PHY_IFACE} -m state --state RELATED,ESTABLISHED -j ACCEPT
${IPTABLES_CMD} -${1} FORWARD -i ${PHY_IFACE} -o ${ZT_IFACE} -j ACCEPT
${IPTABLES_CMD} -${1} FORWARD -i ${ZT_IFACE} -o ${PHY_IFACE} -j DROP
done
;;
"both" )
echo "$2 ${IPTABLES_CMD} rules for bi-directional traffic (local interfaces ${PHY_IFACES} to/from ZeroTier)"
${IPTABLES_CMD} -t nat -${1} POSTROUTING -o ${ZT_IFACE} -j MASQUERADE
for PHY_IFACE in ${PHY_IFACES} ; do
${IPTABLES_CMD} -t nat -${1} POSTROUTING -o ${PHY_IFACE} -j MASQUERADE
${IPTABLES_CMD} -${1} FORWARD -i ${ZT_IFACE} -o ${PHY_IFACE} -j ACCEPT
${IPTABLES_CMD} -${1} FORWARD -i ${PHY_IFACE} -o ${ZT_IFACE} -j ACCEPT
done
;;
* )
echo "Warning: ZEROTIER_ONE_GATEWAY_MODE=${GATEWAY_MODE} is not supported - ignored"
;;
esac
}
# add rules to set up NAT-routing
update_iptables "A" "adding"
# define where the ZeroTier daemon will write its output (if any)
TAIL_PIPE="/tmp/zerotier-ipc-log"
cat /dev/null >"${TAIL_PIPE}"
# start listening and echoing anything that appears there into this process
tail -f "${TAIL_PIPE}" &
# make a note of the process ID for tail
TAIL_PIPE_PID=${!}
# start the ZeroTier daemon in detached state
nohup "$@" </dev/null >"${TAIL_PIPE}" 2>&1 &
# make a note of the process ID
ZEROTIER_DAEMON_PID=${!}
# report
echo "$(date) - ZeroTier daemon is running as process ${ZEROTIER_DAEMON_PID}"
# function to handle cleanup
termination_handler() {
echo "$(date) - terminating ZeroTier-One"
# remove rules
update_iptables "D" "removing"
# relay the termination message to the daemon
# (the pipe listener is cleaned up automatically)
if [ -d "/proc/${ZEROTIER_DAEMON_PID}" ] ; then
kill -TERM ${ZEROTIER_DAEMON_PID}
wait ${ZEROTIER_DAEMON_PID}
fi
}
# set up termination handler (usually catches TERM)
trap termination_handler INT TERM HUP
# suspend this script while the zerotier daemon is running
wait ${ZEROTIER_DAEMON_PID}
# would not usually expect to arrive here inside a Docker container but
# it can happen if the user does a "sudo killall zerotier-one" rather
# that use Docker commands
echo "$(date) - the ZeroTier daemon has quit unexpectedly - cleaning up"
# run the termination handler
termination_handler