-
Notifications
You must be signed in to change notification settings - Fork 86
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
allow switching gateway modes without recreating/restarting the conta…
…iner
- Loading branch information
Showing
3 changed files
with
179 additions
and
53 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
#!/bin/sh | ||
|
||
# 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 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 requested mode | ||
_update_iptables() { | ||
local action | ||
case "${1}" in | ||
"I" ) | ||
action="Inserting" | ||
;; | ||
"A" ) | ||
action="Adding" | ||
;; | ||
"D" ) | ||
action="Deleting" | ||
;; | ||
esac | ||
|
||
case "${2}" in | ||
"inbound" ) | ||
echo "${action} ${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} -j DROP | ||
${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 | ||
done | ||
;; | ||
"outbound" ) | ||
echo "${action} ${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} -j DROP | ||
${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 | ||
done | ||
;; | ||
"both" ) | ||
echo "${action} ${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 | ||
;; | ||
"none" ) | ||
echo "${action} ${IPTABLES_CMD} rules for _no_ traffic (local interfaces ${PHY_IFACES} to/from ZeroTier)" | ||
for PHY_IFACE in ${PHY_IFACES} ; do | ||
${IPTABLES_CMD} -${1} FORWARD -i ${ZT_IFACE} -o ${PHY_IFACE} -j DROP | ||
${IPTABLES_CMD} -${1} FORWARD -i ${PHY_IFACE} -o ${ZT_IFACE} -j DROP | ||
done | ||
esac | ||
} | ||
|
||
# Get current gateway mode by looking up what iptable rules are in place | ||
_get_current_mode() { | ||
|
||
if [ -n "$( ${IPTABLES_CMD} -S -t nat 2> /dev/null | grep "\-o ${ZT_IFACE}" )" ]; then | ||
#either outbound or both | ||
if [ -n "$( ${IPTABLES_CMD} -S | grep "\-i ${ZT_IFACE}.*RELATED" )" ]; then | ||
echo "outbound" | ||
else | ||
echo "both" | ||
fi | ||
elif [ -n "$( ${IPTABLES_CMD} -S | grep "\-i ${ZT_IFACE}.*ACCEPT" )" ]; then | ||
echo "inbound" | ||
elif [ -n "$( ${IPTABLES_CMD} -S | grep "\-i ${ZT_IFACE}.*DROP" )" ]; then | ||
echo "none" | ||
else | ||
echo "disabled" | ||
fi | ||
} | ||
|
||
|
||
_usage() { | ||
echo "Usage: $0 inbound | outbound | both | none | disable | status" | ||
echo "Set, query or disable gateway mode." | ||
echo "" | ||
echo "Commands:" | ||
echo " inbound Only permit traffic from the ZeroTier cloud to the local physical interfaces." | ||
echo " outbound Only permit traffic from the local physical interfaces to the ZeroTier cloud." | ||
echo " both Permit bi-directional traffic between the local physical interfaces and the ZeroTier cloud." | ||
echo " none Block all traffic between the local physical interfaces and the ZeroTier cloud." | ||
echo " disable Remove iptable rules. NOTE: because default forward rule is accept, this behaves like \"both\"." | ||
echo " status Show current gateway mode (e.g. inbound, outbound, etc)" | ||
echo "" | ||
exit $1 | ||
} | ||
|
||
main() { | ||
local i | ||
|
||
local opt | ||
local mode=$( _get_current_mode ) | ||
case "${1}" in | ||
"inbound" ) | ||
if [ ${mode} == "inbound" ]; then | ||
echo "Already in mode inbound." | ||
break | ||
fi | ||
if [ ! ${mode} == "disabled" ]; then | ||
_update_iptables D ${mode} | ||
fi | ||
_update_iptables I inbound | ||
;; | ||
"outbound" ) | ||
if [ ${mode} == "outbound" ] ; then | ||
echo "Already in mode outbound." | ||
break | ||
fi | ||
if [ ! ${mode} == "disabled" ]; then | ||
_update_iptables D ${mode} | ||
fi | ||
_update_iptables I outbound | ||
;; | ||
"both" ) | ||
if [ ${mode} == "both" ]; then | ||
echo "Already in mode both." | ||
break | ||
fi | ||
if [ ! ${mode} == "disabled" ]; then | ||
_update_iptables D ${mode} | ||
fi | ||
_update_iptables I both | ||
;; | ||
"none" ) | ||
if [ ${mode} == "none" ]; then | ||
echo "Already in mode none." | ||
break | ||
fi | ||
if [ ! ${mode} == "disabled" ]; then | ||
_update_iptables D ${mode} | ||
fi | ||
_update_iptables I none | ||
;; | ||
"disable" ) | ||
if [ ${mode} == "disabled" ]; then | ||
echo "Already disabled." | ||
break | ||
fi | ||
if [ ! ${mode} == "disabled" ]; then | ||
_update_iptables D ${mode} | ||
fi | ||
;; | ||
"status" ) | ||
echo ${mode} | ||
;; | ||
"" ) | ||
echo "Please specify a valid argument." | ||
_usage 0 | ||
;; | ||
* ) | ||
echo "Warning: Gateway mode (${1}) is not supported - ignored" | ||
return 1 | ||
;; | ||
esac | ||
return 0 | ||
} | ||
|
||
main "${@}" | ||
exit ${?} | ||
|