Skip to content
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
50 changes: 46 additions & 4 deletions .github/workflows/talos-boot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -281,14 +281,24 @@ jobs:
echo "::error::Gateway を通らない(http=$H https=$S。期待は 301 / 200)"
exit 1

# 受信の防火壁は 2026-10-31 から外してある(bootstrap/talos.md)。外から 10250 が通らないことは見ない。
# 戻したら「外から kubelet」の検査(期待は 000)も戻す(#646)
- name: 外と LAN から届く(443 と 10250)
timeout-minutes: 3
# ノードの受信の防火壁は Cilium の Host Firewall(deploy/cluster/host-firewall.yaml)。ここで当てて、
# 外から 443 は通り 10250 は通らない・LAN からは通る・Pod からノードの IP の Gateway に届く、を見る。
# 後ろの段の talosctl(50000)・kubectl(6443)も LAN(SLIRP の 10.0.0.1)から通ることを見ている
- name: ノードの防火壁(Cilium の Host Firewall)
timeout-minutes: 6
run: |
set -euo pipefail
fail() { echo "::error::$*"; exit 1; }
code() { curl -s -o /dev/null -w '%{http_code}' --max-time 10 "$@" || true; }
until kubectl apply -f deploy/cluster/host-firewall.yaml; do sleep 5; done
# 外からの kubelet が止まるまで待つ(ポリシーがホストに載るまで少しかかる)
for i in $(seq 24); do
KW=$(code -k --max-time 5 https://127.0.0.1:30250/healthz)
[ "$KW" = 000 ] && break
sleep 5
done
echo " 外から kubelet: $KW"
[ "$KW" = 000 ] || fail "外から kubelet(10250)に届いた($KW)。防火壁が効いていない"
# IPv4 の hostfwd は SLIRP の 10.0.0.1(家の LAN と同じ。private-tcp に当たる)から来る。kubelet は認証無しなら 401
K4=$(code -k https://127.0.0.1:20250/healthz)
echo " LAN から kubelet: $K4"
Expand All @@ -298,6 +308,38 @@ jobs:
echo " 外から Gateway: $SW"
[ "$SW" = 200 ] || fail "外から 443 が通らない($SW)"

# **Pod からノード自身の IP の Gateway に届くか。** Pod は fj.doany.io の AAAA(ノードの公開 IPv6)で Forgejo に来る
# (deploy/forgejo/runner.yaml)。防火壁があると conntrack の invalid として捨てられ、TCP はつながるが応答が来なかった
# (2026-10-31 に Talos の防火壁で踏んだ。今は Cilium の Host Firewall なので起きないはず。deploy/cluster/host-firewall.yaml)
- name: Pod からノードの IP の Gateway に届く
timeout-minutes: 4
run: |
set -euo pipefail
cat > /tmp/curl.yaml <<YAML
apiVersion: v1
kind: Pod
metadata: {name: gw-from-pod, namespace: default}
spec:
restartPolicy: Never
securityContext: {runAsNonRoot: true, runAsUser: 65532, seccompProfile: {type: RuntimeDefault}}
containers:
- name: c
image: mirror.gcr.io/curlimages/curl:8.17.0
securityContext: {allowPrivilegeEscalation: false, capabilities: {drop: [ALL]}}
command: [sh, -c]
args:
- |
for ip in $NODE '[240f:6d:842b:1::2]'; do
echo "\$ip \$(curl -sk -o /dev/null -w '%{http_code}' --max-time 10 --connect-to ac.doany.io:443:\$ip:443 https://ac.doany.io/ || true)"
done
YAML
kubectl apply -f /tmp/curl.yaml
kubectl wait --for=jsonpath='{.status.phase}'=Succeeded pod/gw-from-pod --timeout=3m || true
OUT=$(kubectl logs gw-from-pod)
echo "$OUT" | sed 's/^/ /'
kubectl delete pod gw-from-pod --wait=false
[ "$(echo "$OUT" | grep -c ' 200$')" = 2 ] || { echo "::error::Pod からノードの IP の 443 に届かない(上の 000 の行)"; exit 1; }

- name: ディスクとネットワーク
timeout-minutes: 5
run: |
Expand Down
5 changes: 5 additions & 0 deletions bootstrap/cilium-values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ nodePort:
enabled: true
# 範囲は既定のまま。広げないこと: 範囲に入る hostPort を Cilium は張らない(853・8443・3129 が一斉に落ちた)。

# ノード宛ての受信の防火壁(Host Firewall)。規則は ../deploy/cluster/host-firewall.yaml。
# Talos の防火壁ではなくこちらで止める理由もそこに書いてある。
hostFirewall:
enabled: true

# Gateway API。CRD が古いと GatewayClass が無言で止まる。
gatewayAPI:
enabled: true
Expand Down
62 changes: 62 additions & 0 deletions deploy/cluster/host-firewall.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# ノード(ホスト)が受けるものの防火壁。Cilium の Host Firewall(bootstrap/cilium-values.yaml の hostFirewall)。
# ルーターは DMZ と IPv6 ホスト公開で全部のポートをノードに流すので(docs/router.md)、外に出すものはここで決める。
# Talos の防火壁(NetworkDefaultActionConfig)は使わない: conntrack の invalid を捨てる規則を必ず入れ、Envoy の帰りを
# NOTRACK にする Cilium と噛み合わず、Pod からノード自身の IP の Gateway(fj.doany.io)が捨てられた(#652。bootstrap/talos.md)。
# こちらは eBPF で判定するので起きない。
#
# **ホストを選ぶポリシーが 1 つでもあると、書いていない受信は全部止まる。** 外から通すのは docs/router.md の表のポート
# (TCP 80・443・853・3129・6443・8443、UDP 8443・51820)だけ。クラスタの中と内側のアドレス(家の LAN・NetBird・
# リンクローカル)からは全部。Talos の API(50000)・kubelet(10250)・etcd などは外から届かなくなる。表にポートを足すときはここにも足す。
# hostPort(53・853・8443・3129・51820)は Cilium が Pod へ転送するので、ここではなく Pod のポリシーで決まる
# (53 番は ../adguardhome/network-policy.yaml)。
apiVersion: cilium.io/v2
kind: CiliumClusterwideNetworkPolicy
metadata:
name: host-firewall
spec:
nodeSelector: {}
ingress:
- fromEntities:
- cluster
- fromCIDRSet:
- cidr: 10.0.0.0/8
- cidr: 100.64.0.0/10
- cidr: fc00::/7
- cidr: fe80::/10
- fromEntities:
- world
toPorts:
- ports:
- port: "80"
protocol: TCP
- port: "443"
protocol: TCP
- port: "853"
protocol: TCP
- port: "3129"
protocol: TCP
- port: "6443"
protocol: TCP
- port: "8443"
protocol: TCP
- port: "8443"
protocol: UDP
- port: "51820"
protocol: UDP
# ping と、IPv6 で要る ICMPv6(届かない・大きすぎる・時間切れ・引数の誤り・近隣探索)
- fromEntities:
- world
icmps:
- fields:
- {family: IPv4, type: 8}
- {family: IPv4, type: 3}
- {family: IPv4, type: 11}
- {family: IPv6, type: 1}
- {family: IPv6, type: 2}
- {family: IPv6, type: 3}
- {family: IPv6, type: 4}
- {family: IPv6, type: 128}
- {family: IPv6, type: 133}
- {family: IPv6, type: 134}
- {family: IPv6, type: 135}
- {family: IPv6, type: 136}
Loading