Openwrt has a own firewall service called fw3, that supports firewall zones. Docker can bypass the handling of the zone rules in openwrt via custom tables. These are "always" processed before the openwrt firewall. Which is prone to errors! Since not everyone is aware that the firewall of openwrt will not be passed. And this is a security problem because a mapped port is visible on all interfaces and so also on the WAN side. If the firewall handling in docker is switched off, then the port in fw3 must be explicitly released and it cannot happen that the port is accidentally exported to the outside world via the interfaces on the WAN zone. So all rules for the containers should and so must be made in fw3. Signed-off-by: Florian Eckert <fe@dev.tdt.de>
258 lines
7.4 KiB
Bash
Executable file
258 lines
7.4 KiB
Bash
Executable file
#!/bin/sh /etc/rc.common
|
|
|
|
USE_PROCD=1
|
|
START=25
|
|
|
|
extra_command "uciadd" "<interface> <device> <zone> Add docker bridge configuration to network and firewall uci config"
|
|
extra_command "ucidel" "<interface> <device> <zone> Delete docker bridge configuration from network and firewall uci config"
|
|
|
|
DOCKER_CONF_DIR="/tmp/dockerd"
|
|
DOCKERD_CONF="${DOCKER_CONF_DIR}/daemon.json"
|
|
|
|
uci_quiet() {
|
|
uci -q "${@}" >/dev/null
|
|
}
|
|
|
|
json_add_array_string() {
|
|
json_add_string "" "${1}"
|
|
}
|
|
|
|
boot() {
|
|
uciadd
|
|
rc_procd start_service
|
|
}
|
|
|
|
uciupdate() {
|
|
local net="${1}"
|
|
|
|
uci_quiet get network.docker || {
|
|
logger -t "dockerd-init" -p warn "No network uci config section for docker default bridge (docker0) found"
|
|
return
|
|
}
|
|
|
|
[ -z "${net}" ] && {
|
|
logger -t "dockerd-init" -p notice "Removing network uci config options for docker default bridge (docker0)"
|
|
uci_quiet delete network.docker.netmask
|
|
uci_quiet delete network.docker.ipaddr
|
|
uci_quiet commit network
|
|
return
|
|
}
|
|
|
|
eval "$(ipcalc.sh "${net}")"
|
|
logger -t "dockerd-init" -p notice "Updating network uci config option \"${net}\" for docker default bridge (docker0)"
|
|
uci_quiet set network.docker.netmask="${NETMASK}"
|
|
uci_quiet set network.docker.ipaddr="${IP}"
|
|
uci_quiet commit network
|
|
}
|
|
|
|
uciadd() {
|
|
local iface="$1"
|
|
local device="$2"
|
|
local zone="$3"
|
|
|
|
[ -z "$iface" ] && {
|
|
iface="docker"
|
|
device="docker0"
|
|
zone="docker"
|
|
}
|
|
|
|
/etc/init.d/dockerd running && {
|
|
echo "Please stop dockerd service first"
|
|
exit 0
|
|
}
|
|
|
|
# Add network interface
|
|
if ! uci_quiet get network.${iface}; then
|
|
logger -t "dockerd-init" -p notice "Adding docker default interface to network uci config (${iface})"
|
|
uci_quiet add network interface
|
|
uci_quiet rename network.@interface[-1]="${iface}"
|
|
uci_quiet set network.@interface[-1].ifname="${device}"
|
|
uci_quiet set network.@interface[-1].proto="static"
|
|
uci_quiet set network.@interface[-1].auto="0"
|
|
uci_quiet commit network
|
|
fi
|
|
|
|
# Add docker bridge device
|
|
if ! uci_quiet get network.${device}; then
|
|
logger -t "dockerd-init" -p notice "Adding docker default bridge device to network uci config (${device})"
|
|
uci_quiet add network device
|
|
uci_quiet rename network.@device[-1]="${device}"
|
|
uci_quiet set network.@device[-1].type="bridge"
|
|
uci_quiet set network.@device[-1].name="${device}"
|
|
uci_quiet add_list network.@device[-1].ifname="${device}"
|
|
uci_quiet commit network
|
|
fi
|
|
|
|
# Add firewall zone
|
|
if ! uci_quiet get firewall.${zone}; then
|
|
logger -t "dockerd-init" -p notice "Adding docker default firewall zone to firewall uci config (${zone})"
|
|
uci_quiet add firewall zone
|
|
uci_quiet rename firewall.@zone[-1]="${zone}"
|
|
uci_quiet set firewall.@zone[-1].network="${iface}"
|
|
uci_quiet set firewall.@zone[-1].input="REJECT"
|
|
uci_quiet set firewall.@zone[-1].output="ACCEPT"
|
|
uci_quiet set firewall.@zone[-1].forward="REJECT"
|
|
uci_quiet set firewall.@zone[-1].name="${zone}"
|
|
uci_quiet commit firewall
|
|
fi
|
|
|
|
reload_config
|
|
}
|
|
|
|
ucidel() {
|
|
local iface="$1"
|
|
local device="$2"
|
|
local zone="$3"
|
|
|
|
[ -z "$iface" ] && {
|
|
iface="docker"
|
|
device="docker0"
|
|
zone="docker"
|
|
}
|
|
|
|
/etc/init.d/dockerd running && {
|
|
echo "Please stop dockerd service first"
|
|
exit 0
|
|
}
|
|
|
|
if uci_quiet get network.${device}; then
|
|
logger -t "dockerd-init" -p notice "Deleting docker default bridge device from network uci config (${device})"
|
|
uci_quiet delete network.${device}
|
|
uci_quiet commit network
|
|
fi
|
|
|
|
if uci_quiet get network.${iface}; then
|
|
logger -t "dockerd-init" -p notice "Deleting docker default interface from network uci config (${iface})"
|
|
uci_quiet delete network.${iface}
|
|
uci_quiet commit network
|
|
fi
|
|
|
|
if uci_quiet get firewall.${zone}; then
|
|
logger -t "dockerd-init" -p notice "Deleting docker firewall zone from firewall uci config (${zone})"
|
|
uci_quiet delete firewall.${zone}
|
|
uci_quiet commit firewall
|
|
fi
|
|
|
|
reload_config
|
|
}
|
|
|
|
process_config() {
|
|
local alt_config_file data_root log_level iptables bip
|
|
|
|
[ -f /etc/config/dockerd ] || {
|
|
# Use the daemon default configuration
|
|
DOCKERD_CONF=""
|
|
return 0
|
|
}
|
|
|
|
# reset configuration
|
|
rm -fr "${DOCKER_CONF_DIR}"
|
|
mkdir -p "${DOCKER_CONF_DIR}"
|
|
|
|
config_load 'dockerd'
|
|
config_get alt_config_file globals alt_config_file
|
|
[ -n "${alt_config_file}" ] && [ -f "${alt_config_file}" ] && {
|
|
ln -s "${alt_config_file}" "${DOCKERD_CONF}"
|
|
return 0
|
|
}
|
|
|
|
config_get data_root globals data_root "/opt/docker/"
|
|
config_get log_level globals log_level "warn"
|
|
config_get_bool iptables globals iptables "1"
|
|
config_get bip globals bip ""
|
|
|
|
. /usr/share/libubox/jshn.sh
|
|
json_init
|
|
json_add_string "data-root" "${data_root}"
|
|
json_add_string "log-level" "${log_level}"
|
|
[ -z "${bip}" ] || json_add_string "bip" "${bip}"
|
|
json_add_array "registry-mirrors"
|
|
config_list_foreach globals registry_mirrors json_add_array_string
|
|
json_close_array
|
|
json_add_array "hosts"
|
|
config_list_foreach globals hosts json_add_array_string
|
|
json_close_array
|
|
|
|
json_add_boolean iptables "${iptables}"
|
|
[ "${iptables}" -ne "0" ] && config_foreach iptables_add_blocking_rule firewall
|
|
|
|
json_dump > "${DOCKERD_CONF}"
|
|
|
|
uciupdate "${bip}"
|
|
}
|
|
|
|
start_service() {
|
|
local nofile=$(cat /proc/sys/fs/nr_open)
|
|
|
|
process_config
|
|
|
|
procd_open_instance
|
|
procd_set_param stderr 1
|
|
if [ -z "${DOCKERD_CONF}" ]; then
|
|
procd_set_param command /usr/bin/dockerd
|
|
else
|
|
procd_set_param command /usr/bin/dockerd --config-file="${DOCKERD_CONF}"
|
|
fi
|
|
procd_set_param limits nofile="${nofile} ${nofile}"
|
|
procd_close_instance
|
|
}
|
|
|
|
reload_service() {
|
|
process_config
|
|
procd_send_signal dockerd
|
|
}
|
|
|
|
service_triggers() {
|
|
procd_add_reload_trigger 'dockerd'
|
|
}
|
|
|
|
add_docker_firewall_rules() {
|
|
. /lib/functions/network.sh
|
|
local device interface="${1}"
|
|
|
|
# Ignore errors as it might already be present
|
|
iptables --table filter --new DOCKER-USER 2>/dev/null
|
|
network_get_physdev device "${interface}"
|
|
if ! iptables --table filter --check DOCKER-USER --in-interface "${device}" --out-interface docker0 --jump DROP 2>/dev/null; then
|
|
iptables --table filter --insert DOCKER-USER --in-interface "${device}" --out-interface docker0 --jump DROP
|
|
fi
|
|
}
|
|
|
|
ip4tables_remove_nat() {
|
|
iptables --table nat --delete OUTPUT ! --destination 127.0.0.0/8 --match addrtype --dst-type LOCAL --jump DOCKER
|
|
iptables --table nat --delete PREROUTING --match addrtype --dst-type LOCAL --jump DOCKER
|
|
|
|
iptables --table nat --flush DOCKER
|
|
iptables --table nat --delete-chain DOCKER
|
|
}
|
|
|
|
ip4tables_remove_filter() {
|
|
iptables --table filter --delete FORWARD --jump DOCKER-USER
|
|
iptables --table filter --delete FORWARD --jump DOCKER-ISOLATION-STAGE-1
|
|
iptables --table filter --delete FORWARD --out-interface docker0 --jump DOCKER
|
|
iptables --table filter --delete FORWARD --out-interface docker0 --match conntrack --ctstate RELATED,ESTABLISHED --jump ACCEPT
|
|
iptables --table filter --delete FORWARD --in-interface docker0 --out-interface docker0 --jump ACCEPT
|
|
iptables --table filter --delete FORWARD --in-interface docker0 ! --out-interface docker0 --jump ACCEPT
|
|
|
|
iptables --table filter --flush DOCKER
|
|
iptables --table filter --flush DOCKER-ISOLATION-STAGE-1
|
|
iptables --table filter --flush DOCKER-ISOLATION-STAGE-2
|
|
iptables --table filter --flush DOCKER-USER
|
|
|
|
iptables --table filter --delete-chain DOCKER
|
|
iptables --table filter --delete-chain DOCKER-ISOLATION-STAGE-1
|
|
iptables --table filter --delete-chain DOCKER-ISOLATION-STAGE-2
|
|
iptables --table filter --delete-chain DOCKER-USER
|
|
}
|
|
|
|
ip4tables_remove() {
|
|
ip4tables_remove_nat
|
|
ip4tables_remove_filter
|
|
}
|
|
|
|
stop_service() {
|
|
if /etc/init.d/dockerd running; then
|
|
service_stop "/usr/bin/dockerd"
|
|
ip4tables_remove
|
|
fi
|
|
}
|