Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: [NODE-1530] Allow local network to access metrics through firewall #2703

Merged
merged 7 commits into from
Nov 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion ic-os/components/hostos.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,9 @@ component_files = {
Label("networking/fallback.conf"): "/etc/systemd/resolved.conf.d/fallback.conf",
Label("networking/resolv.conf"): "/etc/resolv.conf",
Label("networking/network-tweaks.conf"): "/etc/sysctl.d/network-tweaks.conf",
Label("networking/nftables/nftables-hostos.conf"): "/etc/nftables.conf",
Label("networking/nftables/hostos/nftables.template"): "/opt/ic/share/nftables.template",
Label("networking/nftables/hostos/setup-nftables.service"): "/etc/systemd/system/setup-nftables.service",
Label("networking/nftables/hostos/setup-nftables.sh"): "/opt/ic/bin/setup-nftables.sh",
Label("networking/hosts"): "/etc/hosts",

# ssh
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,12 +228,19 @@ QUERY_STATS_EPOCH_LENGTH="${query_stats_epoch_length:-600}"
# TODO: If the Jaeger address is not specified the config file will contain Some(""). This needs to be fixed.
JAEGER_ADDR="${jaeger_addr:-}"

# TODO: Should pass prefix directly
if ! IPV6_PREFIX=$(echo "${IPV6_ADDRESS}" | sed -E -e 's/:/#/4' -e '/#/!q1' -e 's/#.*/::\/64/'); then
# If address does not substitute correctly, fallback to loopback for easy templating
IPV6_PREFIX="::1/128"
fi

if [ "${IPV6_ADDRESS}" == "" ]; then
echo "Cannot determine an IPv6 address, aborting"
exit 1
fi

sed -e "s@{{ ipv6_address }}@${IPV6_ADDRESS}@" \
-e "s@{{ ipv6_prefix }}@${IPV6_PREFIX}@" \
-e "s@{{ ipv4_address }}@${IPV4_ADDRESS}@" \
-e "s@{{ ipv4_gateway }}@${IPV4_GATEWAY}@" \
-e "s@{{ domain }}@${DOMAIN}@" \
Expand Down
1 change: 1 addition & 0 deletions ic-os/components/ic/generate-ic-config/ic.json5.template
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ table ip6 filter {\n\
icmpv6 type nd-router-advert accept\n\
icmpv6 type nd-neighbor-solicit accept\n\
icmpv6 type nd-neighbor-advert accept\n\
ip6 saddr { {{ ipv6_prefix }} } ct state { new } tcp dport { 7070, 9090, 9091, 9100, 19531, 19100 } accept\n\
ip6 saddr { hostos } ct state { new } tcp dport { 42372 } accept # Allow access from HostOS metrics-proxy so GuestOS metrics-proxy can proxy certain metrics to HostOS.\n\
<<IPv6_TCP_RULES>>\n\
<<IPv6_UDP_RULES>>\n\
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,14 @@ table ip6 filter {
accept
}

set local_prefix {
type ipv6_addr
flags interval
elements = {
{{ ipv6_prefix }}
Bownairo marked this conversation as resolved.
Show resolved Hide resolved
}
}

chain INPUT {
type filter hook input priority filter; policy drop;
iif "lo" accept
Expand All @@ -192,6 +200,7 @@ table ip6 filter {
ip6 saddr @dfinity_dcs ct state { new } tcp dport { 22, 9100, 19531, 19100 } accept
ip6 saddr @telemetry_clients ct state { new } tcp dport { 9100, 19531, 19100 } accept
ip6 saddr @node_providers ct state { new } tcp dport { 22, 9100, 19531 } accept
ip6 saddr @local_prefix ct state { new } tcp dport { 9100, 19531, 19100 } accept
tcp dport { 42372 } goto metrics_proxy
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[Unit]
Description=Generate Firewall Configuration
# We must wait for IC bootstrap to complete: It writes various
# state files and may also be needed to obtain network config.
After=bootstrap-ic-node.service
Wants=bootstrap-ic-node.service
# We must also wait for storage permission fixup to have finished.
After=setup-permissions.service
Wants=setup-permissions.service
Before=nftables.service
Wants=nftables.service

[Service]
Type=oneshot
ExecStart=/opt/ic/bin/setup-nftables.sh -n /boot/config/config.ini -i /opt/ic/share/nftables.template -o /run/ic-node/nftables-ruleset/nftables.conf

[Install]
WantedBy=multi-user.target
70 changes: 70 additions & 0 deletions ic-os/components/networking/nftables/hostos/setup-nftables.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#!/bin/bash

# Substitute correct configuration parameters into nftables.conf.

function usage() {
cat <<EOF
Usage:
setup-nftables -n config.ini -i nftables.template -o nftables.conf

Generate nftables config from template file.

-n config.ini: network configuration description file
-i infile: input ic.json5.template file
-o outfile: output ic.json5 file
EOF
}

# XXX: the following function is duplicate with generate-network-config.sh
# -- consolidate
#
# Read the network config variables from file. The file must be of the form
# "key=value" for each line with a specific set of keys permissible (see
# code below).
#
# Arguments:
# - $1: Name of the file to be read.
function read_network_variables() {
# Read limited set of keys. Be extra-careful quoting values as it could
# otherwise lead to executing arbitrary shell code!
while IFS="=" read -r key value; do
case "$key" in
"ipv6_prefix") ipv6_prefix="${value}" ;;
esac
done <"$1"
}
Bownairo marked this conversation as resolved.
Show resolved Hide resolved

while getopts "n:i:o:" OPT; do
case "${OPT}" in
n)
NETWORK_CONFIG_FILE="${OPTARG}"
;;
i)
IN_FILE="${OPTARG}"
;;
o)
OUT_FILE="${OPTARG}"
;;
*)
usage
exit 1
;;
esac
done

if [ "${IN_FILE}" == "" -o "${OUT_FILE}" == "" ]; then
usage
exit 1
fi

# TODO: This should be pulled from the system, in case of configuration via RA.
if [ "${NETWORK_CONFIG_FILE}" != "" -a -e "${NETWORK_CONFIG_FILE}" ]; then
read_network_variables "${NETWORK_CONFIG_FILE}"
fi

IPV6_PREFIX="${ipv6_prefix:+${ipv6_prefix}::/64}" # Add suffix to prefix if found
IPV6_PREFIX="${IPV6_PREFIX:-::1/128}" # Default to loopback for easy templating

mkdir -p /run/ic-node/nftables-ruleset/
sed -e "s@{{ ipv6_prefix }}@${IPV6_PREFIX}@" \
"${IN_FILE}" >"${OUT_FILE}"
4 changes: 4 additions & 0 deletions ic-os/hostos/context/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ RUN systemctl disable \

# ------ HOSTOS WORK ---------------------------------------------

# Divert symbolic link for dynamically generated nftables
# ruleset.
RUN ln -sf /run/ic-node/nftables-ruleset/nftables.conf /etc/nftables.conf

ARG ROOT_PASSWORD=
RUN \
if [ "${ROOT_PASSWORD}" != "" ]; then \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ table ip6 filter {
icmpv6 type nd-router-advert accept
icmpv6 type nd-neighbor-solicit accept
icmpv6 type nd-neighbor-advert accept
ip6 saddr { {{ ipv6_prefix }} } ct state { new } tcp dport { 7070, 9090, 9091, 9100, 19531, 19100 } accept
ip6 saddr { hostos } ct state { new } tcp dport { 42372 } accept # Allow access from HostOS metrics-proxy so GuestOS metrics-proxy can proxy certain metrics to HostOS.
ip6 saddr {::ffff:5.5.5.5} ct state { new } tcp dport {1005} accept # node_gwp4o-eaaaa-aaaaa-aaaap-2ai
ip6 saddr {::ffff:3.3.3.3} ct state { new } tcp dport {1003} accept # subnet_yndj2-3ybaa-aaaaa-aaaap-yai
Expand Down