允许GitHub操作中断的iptables规则(链默认为DROP)



假设我的iptables规则在INPUT和OUTPUT链上默认为DROP,那么为了防止在GitHub Actions中运行的脚本无限期停滞,我必须向链中添加的最小规则集是什么?

我正在为我的开源应用程序的CI/CD基础设施使用(免费(GitHub Actions。当我向github.com推送更改时,它会自动启动微软云中的Ubuntu 18.04 linux服务器,该服务器会检查我的回购并执行BASH脚本来构建我的应用程序。

出于安全原因,在构建脚本的早期,我安装并设置了一些非常严格的iptables规则,这些规则在INPUTOUTPUT链上默认为DROP。我在INPUT上为127.0.0.1RELATED/ESTABLISHED在防火墙上戳了一个洞,只允许_apt用户通过OUTPUT发送流量。

当我在本地系统上的docker容器中运行构建脚本时,这非常有效。但是,正如我刚刚了解到的那样,当它使用GitHub Actions运行时,它会无限期地停滞。显然,实例本身需要能够与GitHub的服务器通信才能完成。我似乎打破了这一点。

因此,问题是:我应该在iptablesINPUTOUTPUT链中添加什么-j ACCEPT规则,才能只允许GitHub Actions执行的基本必需品照常进行?

作为参考,以下是我的构建脚本中设置防火墙的片段:

##################
# SETUP IPTABLES #
##################
# We setup iptables so that only the apt user (and therefore the apt command)
# can access the internet. We don't want insecure tools like `pip` to download
# unsafe code from the internet.
${SUDO} iptables-save > /tmp/iptables-save.`date "+%Y%m%d_%H%M%S"`
${SUDO} iptables -A INPUT -i lo -j ACCEPT
${SUDO} iptables -A INPUT -s 127.0.0.1/32 -j DROP
${SUDO} iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
${SUDO} iptables -A INPUT -j DROP
${SUDO} iptables -A OUTPUT -s 127.0.0.1/32 -d 127.0.0.1/32 -j ACCEPT
${SUDO} iptables -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
${SUDO} iptables -A OUTPUT -m owner --uid-owner 100 -j ACCEPT # apt uid = 100
${SUDO} iptables -A OUTPUT -j DROP
${SUDO} ip6tables-save > /tmp/ip6tables-save.`date "+%Y%m%d_%H%M%S"`
${SUDO} ip6tables -A INPUT -i lo -j ACCEPT
${SUDO} ip6tables -A INPUT -s ::1/128 -j DROP
${SUDO} ip6tables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
${SUDO} ip6tables -A INPUT -j DROP
${SUDO} ip6tables -A OUTPUT -s ::1/128 -d ::1/128 -j ACCEPT
${SUDO} ip6tables -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
${SUDO} ip6tables -A OUTPUT -m owner --uid-owner 100 -j ACCEPT
${SUDO} ip6tables -A OUTPUT -j DROP
# attempt to access the internet as root. If it works, exit 1
curl -s 1.1.1.1
if [ $? -eq 0 ]; then
echo "ERROR: iptables isn't blocking internet access to unsafe tools. You may need to run this as root (and you should do it inside a VM)"
exit 1
fi

这可以通过在docker容器中运行构建脚本并在该容器中应用iptables规则来实现,这不会影响主机runner的连接。

例如,如果以下脚本在GitHub Actions作业(在Ubuntu 18.04 GitHub共享运行程序中(中执行,它将在除_apt用户之外没有互联网连接的debian docker容器中运行构建脚本(docker_script.sh(。

#!/bin/bash
set -x
###################
# INSTALL DEPENDS #
###################
apt-get -y install docker.io
##################
# DOWNLOAD IMAGE #
##################
# At the time of writing, Docker Content Trust is 100% security theater without
# explicitly adding the root public keys to the $HOME/.docker/trust/ directory
#
#  * https://github.com/BusKill/buskill-app/issues/6#issuecomment-700050760
#  * https://security.stackexchange.com/questions/238529/how-to-list-all-of-the-known-root-keys-in-docker-docker-content-trust
#  * https://github.com/docker/cli/issues/2752
docker -D pull debian:stable-slim
#################
# CREATE SCRIPT #
#################
tmpDir=`mktemp -d`
pushd "${tmpDir}"
cat << EOF > docker_script.sh
#!/bin/bash
set -x
# SETTINGS #
SUDO=/usr/bin/sudo
# DEPENDS #
${SUDO} apt-get update
${SUDO} apt-get install iptables curl
# IPTABLES #
# We setup iptables so that only the apt user (and therefore the apt command)
# can access the internet. We don't want insecure tools like `pip` to download
# unsafe code from the internet.
${SUDO} iptables-save > /tmp/iptables-save.`date "+%Y%m%d_%H%M%S"`
${SUDO} iptables -A INPUT -i lo -j ACCEPT
${SUDO} iptables -A INPUT -s 127.0.0.1/32 -j DROP
${SUDO} iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
${SUDO} iptables -A INPUT -j DROP
${SUDO} iptables -A OUTPUT -s 127.0.0.1/32 -d 127.0.0.1/32 -j ACCEPT
${SUDO} iptables -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
${SUDO} iptables -A OUTPUT -m owner --uid-owner 100 -j ACCEPT # apt uid = 100
${SUDO} iptables -A OUTPUT -j DROP
${SUDO} ip6tables-save > /tmp/ip6tables-save.`date "+%Y%m%d_%H%M%S"`
${SUDO} ip6tables -A INPUT -i lo -j ACCEPT
${SUDO} ip6tables -A INPUT -s ::1/128 -j DROP
${SUDO} ip6tables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
${SUDO} ip6tables -A INPUT -j DROP
${SUDO} ip6tables -A OUTPUT -s ::1/128 -d ::1/128 -j ACCEPT
${SUDO} ip6tables -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
${SUDO} ip6tables -A OUTPUT -m owner --uid-owner 100 -j ACCEPT
${SUDO} ip6tables -A OUTPUT -j DROP
# attempt to access the internet as root. If it works, exit 1
curl 1.1.1.1
if [ $? -eq 0 ]; then
echo "ERROR: iptables isn't blocking internet access to unsafe tools. You may need to run this as root (and you should do it inside a VM)"
exit 1
fi
# BUILD #
# ...
# <DO BUILD HERE>
# ...
exit 0
EOF
chmod +x docker_script.sh
##############
# DOCKER RUN #
##############
docker run --rm --cap-add "NET_ADMIN" -v "${tmpDir}:/root/shared_volume" debian:stable-slim /bin/bash -c "cd /root/shared_volume && docker_script.sh"
# exit cleanly
exit 0

注意:

  1. 为了添加NET_ADMIN功能,您必须手动执行docker run命令,而不仅仅是在GitHub Actions yaml文件中指定container:。另请参阅如何在具有附加功能的docker容器中运行脚本(docker exec…--cap-add…(

  2. 除非在调用docker pull之前固定根签名密钥,否则这是一个安全风险。另请参阅https://security.stackexchange.com/questions/238529/how-to-list-all-of-the-known-root-keys-in-docker-docker-content-trust

  3. 以上脚本应以root用户身份执行。例如,在GitHub Actions工作流中的步骤的run:键中,为其添加sudo

您所做的工作不可靠,您应该采用不同的解决方案。为了实现这一点,你需要知道你正在操作的网络的布局,以及相关GitHub操作流程运行的用户,而GitHub既没有记录也没有保证该设置的一致性。

因此,即使你确实找到了解决方案,GitHub也可能会通过在新的数据中心或其他不同的网络上运行代码,或者通过更改运行其流程的用户,或与你的设置相关的其他属性来破坏它。

如果你担心你正在运行的代码下载你不想要的东西,最好将其配置为不这样做,一开始就不运行代码,或者验证你想要的代码是否运行。例如,在一个使用C库的Rust程序中,如果我担心的话,我可能会验证二进制文件是否动态链接到系统库,而不是让Cargo构建自己的版本。如果你只想使用系统包,你可以配置任何每种语言的包管理器在localhost上查找镜像,如果他们试图访问互联网,镜像就会失败,如果你愿意,甚至可以测试一下。

最新更新