@@ -7,8 +7,10 @@ import (
77 "errors"
88 "fmt"
99 "net/netip"
10+ "strconv"
1011
1112 "github.com/containerd/log"
13+ "github.com/moby/moby/v2/daemon/libnetwork/internal/nftables"
1214 "github.com/moby/moby/v2/daemon/libnetwork/types"
1315)
1416
@@ -20,44 +22,47 @@ func (n *network) AddLink(ctx context.Context, parentIP, childIP netip.Addr, por
2022 return errors .New ("cannot link to a container with an empty child IP address" )
2123 }
2224
23- chain := n . fw . table4 . Chain ( ctx , chainFilterFwdIn ( n . config . IfName ))
25+ tm := nftables. Modifier {}
2426 for _ , port := range ports {
25- for _ , rule := range legacyLinkRules (parentIP , childIP , port ) {
26- if err := chain .AppendRule (ctx , fwdInLegacyLinksRuleGroup , rule ); err != nil {
27- return err
28- }
29- }
27+ updateLegacyLinkRules (tm .Create , chainFilterFwdIn (n .config .IfName ), parentIP , childIP , port )
3028 }
31- if err := nftApply ( ctx , n .fw .table4 ); err != nil {
29+ if err := n .fw .table4 . Apply ( ctx , tm ); err != nil {
3230 return fmt .Errorf ("adding rules for bridge %s: %w" , n .config .IfName , err )
3331 }
3432 return nil
3533}
3634
3735func (n * network ) DelLink (ctx context.Context , parentIP , childIP netip.Addr , ports []types.TransportPort ) {
38- chain := n . fw . table4 . Chain ( ctx , chainFilterFwdIn ( n . config . IfName ))
36+ tm := nftables. Modifier {}
3937 for _ , port := range ports {
40- for _ , rule := range legacyLinkRules (parentIP , childIP , port ) {
41- if err := chain .DeleteRule (ctx , fwdInLegacyLinksRuleGroup , rule ); err != nil {
42- log .G (ctx ).WithFields (log.Fields {
43- "rule" : rule ,
44- "error" : err ,
45- }).Warn ("Failed to remove link between containers" )
46- }
47- }
38+ updateLegacyLinkRules (tm .Delete , chainFilterFwdIn (n .config .IfName ), parentIP , childIP , port )
4839 }
49- if err := nftApply ( ctx , n .fw .table4 ); err != nil {
40+ if err := n .fw .table4 . Apply ( ctx , tm ); err != nil {
5041 log .G (ctx ).WithError (err ).Warn ("Removing link, failed to update nftables" )
5142 }
5243}
5344
54- func legacyLinkRules ( parentIP , childIP netip.Addr , port types.TransportPort ) [] string {
45+ func updateLegacyLinkRules ( updater func ( command nftables. Obj ), chainName string , parentIP , childIP netip.Addr , port types.TransportPort ) {
5546 // TODO(robmry) - could combine rules for each proto by using an anonymous set.
56- return []string {
57- // Match the iptables implementation, but without checking iifname/oifname (not needed
58- // because the addresses belong to the bridge).
59- fmt .Sprintf ("ip saddr %s ip daddr %s %s dport %d counter accept" , parentIP .Unmap (), childIP .Unmap (), port .Proto , port .Port ),
60- // Conntrack will allow responses. So, this must be to allow unsolicited packets from an exposed port.
61- fmt .Sprintf ("ip daddr %s ip saddr %s %s sport %d counter accept" , parentIP .Unmap (), childIP .Unmap (), port .Proto , port .Port ),
62- }
47+ // Match the iptables implementation, but without checking iifname/oifname (not needed
48+ // because the addresses belong to the bridge).
49+ updater (nftables.Rule {
50+ Chain : chainName ,
51+ Group : fwdInLegacyLinksRuleGroup ,
52+ Rule : []string {
53+ "ip saddr" , parentIP .Unmap ().String (),
54+ "ip daddr" , childIP .Unmap ().String (), port .Proto .String (), "dport" , strconv .Itoa (int (port .Port )),
55+ "counter accept" ,
56+ },
57+ })
58+ // Conntrack will allow responses. So, this must be to allow unsolicited packets from an exposed port.
59+ updater (nftables.Rule {
60+ Chain : chainName ,
61+ Group : fwdInLegacyLinksRuleGroup ,
62+ Rule : []string {
63+ "ip saddr" , childIP .Unmap ().String (), port .Proto .String (), "sport" , strconv .Itoa (int (port .Port )),
64+ "ip daddr" , parentIP .Unmap ().String (),
65+ "counter accept" ,
66+ },
67+ })
6368}
0 commit comments