Skip to content

Commit 7ed3681

Browse files
committed
tailcfg: Add FirewallMode to NetInfo to record wether host using iptables or nftables
To record wether user is using iptables or nftables after we add support to nftables on linux, we are adding a field FirewallMode to NetInfo in HostInfo to reflect what firewall mode the host is running, and form metrics. The information is gained from a global constant in hostinfo.go. We set it when selection heuristic made the decision, and magicsock reports this to control. Updates: tailscale/corp#13943 Signed-off-by: KevinLiang10 <kevinliang@tailscale.com>
1 parent 95d776b commit 7ed3681

File tree

7 files changed

+33
-3
lines changed

7 files changed

+33
-3
lines changed

hostinfo/hostinfo.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ var (
171171
desktopAtomic atomic.Value // of opt.Bool
172172
packagingType atomic.Value // of string
173173
appType atomic.Value // of string
174+
firewallMode atomic.Value // of string
174175
)
175176

176177
// SetPushDeviceToken sets the device token for use in Hostinfo updates.
@@ -182,6 +183,9 @@ func SetDeviceModel(model string) { deviceModelAtomic.Store(model) }
182183
// SetOSVersion sets the OS version.
183184
func SetOSVersion(v string) { osVersionAtomic.Store(v) }
184185

186+
// SetFirewallMode sets the firewall mode for the app.
187+
func SetFirewallMode(v string) { firewallMode.Store(v) }
188+
185189
// SetPackage sets the packaging type for the app.
186190
//
187191
// As of 2022-03-25, this is used by Android ("nogoogle" for the
@@ -203,6 +207,13 @@ func pushDeviceToken() string {
203207
return s
204208
}
205209

210+
// FirewallMode returns the firewall mode for the app.
211+
// It is empty if unset.
212+
func FirewallMode() string {
213+
s, _ := firewallMode.Load().(string)
214+
return s
215+
}
216+
206217
func desktop() (ret opt.Bool) {
207218
if runtime.GOOS != "linux" {
208219
return opt.Bool("")

tailcfg/tailcfg.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -734,17 +734,22 @@ type NetInfo struct {
734734
// the control plane.
735735
DERPLatency map[string]float64 `json:",omitempty"`
736736

737+
// FirewallMode is the current firewall utility in use by router (iptables, nftables).
738+
// FirewallMode ipt means iptables, nft means nftables. When it's empty user is not using
739+
// our netfilter runners to manage firewall rules.
740+
FirewallMode string `json:",omitempty"`
741+
737742
// Update BasicallyEqual when adding fields.
738743
}
739744

740745
func (ni *NetInfo) String() string {
741746
if ni == nil {
742747
return "NetInfo(nil)"
743748
}
744-
return fmt.Sprintf("NetInfo{varies=%v hairpin=%v ipv6=%v ipv6os=%v udp=%v icmpv4=%v derp=#%v portmap=%v link=%q}",
749+
return fmt.Sprintf("NetInfo{varies=%v hairpin=%v ipv6=%v ipv6os=%v udp=%v icmpv4=%v derp=#%v portmap=%v link=%q firewallmode=%q}",
745750
ni.MappingVariesByDestIP, ni.HairPinning, ni.WorkingIPv6,
746751
ni.OSHasIPv6, ni.WorkingUDP, ni.WorkingICMPv4,
747-
ni.PreferredDERP, ni.portMapSummary(), ni.LinkType)
752+
ni.PreferredDERP, ni.portMapSummary(), ni.LinkType, ni.FirewallMode)
748753
}
749754

750755
func (ni *NetInfo) portMapSummary() string {
@@ -792,7 +797,8 @@ func (ni *NetInfo) BasicallyEqual(ni2 *NetInfo) bool {
792797
ni.PMP == ni2.PMP &&
793798
ni.PCP == ni2.PCP &&
794799
ni.PreferredDERP == ni2.PreferredDERP &&
795-
ni.LinkType == ni2.LinkType
800+
ni.LinkType == ni2.LinkType &&
801+
ni.FirewallMode == ni2.FirewallMode
796802
}
797803

798804
// Equal reports whether h and h2 are equal.

tailcfg/tailcfg_clone.go

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tailcfg/tailcfg_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,7 @@ func TestNetInfoFields(t *testing.T) {
571571
"PreferredDERP",
572572
"LinkType",
573573
"DERPLatency",
574+
"FirewallMode",
574575
}
575576
if have := fieldsOf(reflect.TypeOf(NetInfo{})); !reflect.DeepEqual(have, handled) {
576577
t.Errorf("NetInfo.Clone/BasicallyEqually check might be out of sync\nfields: %q\nhandled: %q\n",

tailcfg/tailcfg_view.go

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

wgengine/magicsock/magicsock.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,7 @@ func (c *Conn) updateNetInfo(ctx context.Context) (*netcheck.Report, error) {
640640
if !c.setNearestDERP(ni.PreferredDERP) {
641641
ni.PreferredDERP = 0
642642
}
643+
ni.FirewallMode = hostinfo.FirewallMode()
643644

644645
c.callNetInfoCallback(ni)
645646
return report, nil

wgengine/router/router_linux.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"golang.org/x/sys/unix"
2323
"golang.org/x/time/rate"
2424
"tailscale.com/envknob"
25+
"tailscale.com/hostinfo"
2526
"tailscale.com/net/netmon"
2627
"tailscale.com/types/logger"
2728
"tailscale.com/types/preftype"
@@ -97,29 +98,36 @@ func chooseFireWallMode(logf logger.Logf, det tableDetector) linuxfw.FirewallMod
9798
case envknob.String("TS_DEBUG_FIREWALL_MODE") == "nftables":
9899
// TODO(KevinLiang10): Updates to a flag
99100
logf("router: envknob TS_DEBUG_FIREWALL_MODE=nftables set")
101+
hostinfo.SetFirewallMode("nft-forced")
100102
return linuxfw.FirewallModeNfTables
101103
case envknob.String("TS_DEBUG_FIREWALL_MODE") == "iptables":
102104
logf("router: envknob TS_DEBUG_FIREWALL_MODE=iptables set")
105+
hostinfo.SetFirewallMode("ipt-forced")
103106
return linuxfw.FirewallModeIPTables
104107
case nftRuleCount > 0 && iptRuleCount == 0:
105108
logf("router: nftables is currently in use")
109+
hostinfo.SetFirewallMode("nft-inuse")
106110
return linuxfw.FirewallModeNfTables
107111
case iptRuleCount > 0 && nftRuleCount == 0:
108112
logf("router: iptables is currently in use")
113+
hostinfo.SetFirewallMode("ipt-inuse")
109114
return linuxfw.FirewallModeIPTables
110115
case nftAva:
111116
// if both iptables and nftables are available but
112117
// neither/both are currently used, use nftables.
113118
logf("router: nftables is available")
119+
hostinfo.SetFirewallMode("nft")
114120
return linuxfw.FirewallModeNfTables
115121
case iptAva:
116122
logf("router: iptables is available")
123+
hostinfo.SetFirewallMode("ipt")
117124
return linuxfw.FirewallModeIPTables
118125
default:
119126
// if neither iptables nor nftables are available, use iptablesRunner as a dummy
120127
// runner which exists but won't do anything. Creating iptablesRunner errors only
121128
// if the iptables command is missing or doesn’t support "--version", as long as it
122129
// can determine a version then it’ll carry on.
130+
hostinfo.SetFirewallMode("ipt-fb")
123131
return linuxfw.FirewallModeIPTables
124132
}
125133
}

0 commit comments

Comments
 (0)