Merge 36137a4d6a
into 745931415c
This commit is contained in:
commit
4ae19eb12a
|
@ -10,6 +10,7 @@ import (
|
|||
"os"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"tailscale.com/types/lazy"
|
||||
"tailscale.com/util/lineread"
|
||||
|
@ -31,6 +32,7 @@ const (
|
|||
WDMyCloud = Distro("wdmycloud")
|
||||
Unraid = Distro("unraid")
|
||||
Alpine = Distro("alpine")
|
||||
UDMPro = Distro("udmpro")
|
||||
)
|
||||
|
||||
var distro lazy.SyncValue[Distro]
|
||||
|
@ -76,6 +78,9 @@ func linuxDistro() Distro {
|
|||
case have("/usr/local/bin/freenas-debug"):
|
||||
// TrueNAS Scale runs on debian
|
||||
return TrueNAS
|
||||
case isUDMPro():
|
||||
// UDM-Pro runs on debian
|
||||
return UDMPro
|
||||
case have("/etc/debian_version"):
|
||||
return Debian
|
||||
case have("/etc/arch-release"):
|
||||
|
@ -147,3 +152,30 @@ func DSMVersion() int {
|
|||
return v
|
||||
})
|
||||
}
|
||||
|
||||
// isUDMPro checks a couple of files known to exist on a UDM-Pro and returns
|
||||
// true if the expected content exists in the files.
|
||||
func isUDMPro() bool {
|
||||
if exists, err := fileContainsString("/etc/board.info", "UDMPRO"); err == nil && exists {
|
||||
return true
|
||||
}
|
||||
if exists, err := fileContainsString("/etc/board.info", "Dream Machine PRO"); err == nil && exists {
|
||||
return true
|
||||
}
|
||||
if exists, err := fileContainsString("/sys/firmware/devicetree/base/soc/board-cfg/id", "udm pro"); err == nil && exists {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// fileContainsString is used to determine if a string exists in a file. This is
|
||||
// not efficient for larger files. If you want to use this function to parse
|
||||
// large files, please refactor to use `io.LimitedReader`.
|
||||
func fileContainsString(filePath, searchString string) (bool, error) {
|
||||
data, err := os.ReadFile(filePath)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return strings.Contains(string(data), searchString), nil
|
||||
}
|
||||
|
|
|
@ -1101,7 +1101,9 @@ var (
|
|||
tailscaleRouteTable = newRouteTable("tailscale", 52)
|
||||
)
|
||||
|
||||
// ipRules are the policy routing rules that Tailscale uses.
|
||||
// baseIPRules are the policy routing rules that Tailscale uses, when not
|
||||
// running on a UDM-Pro.
|
||||
//
|
||||
// The priority is the value represented here added to r.ipPolicyPrefBase,
|
||||
// which is usually 5200.
|
||||
//
|
||||
|
@ -1116,7 +1118,7 @@ var (
|
|||
// and 'ip rule' implementations (including busybox), don't support
|
||||
// checking for the lack of a fwmark, only the presence. The technique
|
||||
// below works even on very old kernels.
|
||||
var ipRules = []netlink.Rule{
|
||||
var baseIPRules = []netlink.Rule{
|
||||
// Packets from us, tagged with our fwmark, first try the kernel's
|
||||
// main routing table.
|
||||
{
|
||||
|
@ -1152,6 +1154,34 @@ var ipRules = []netlink.Rule{
|
|||
// usual rules (pref 32766 and 32767, ie. main and default).
|
||||
}
|
||||
|
||||
// udmProIPRules are the policy routing rules that Tailscale uses, when running
|
||||
// on a UDM-Pro.
|
||||
//
|
||||
// The priority is the value represented here added to
|
||||
// r.ipPolicyPrefBase, which is usually 5200.
|
||||
//
|
||||
// This represents an experiment that will be used to gather more information.
|
||||
// If this goes well, Tailscale may opt to use this for all of Linux.
|
||||
var udmProIPRules = []netlink.Rule{
|
||||
// non-fwmark packets fall through to the usual rules (pref 32766 and 32767,
|
||||
// ie. main and default).
|
||||
{
|
||||
Priority: 70,
|
||||
Invert: true,
|
||||
Mark: linuxfw.TailscaleBypassMarkNum,
|
||||
Table: tailscaleRouteTable.Num,
|
||||
},
|
||||
}
|
||||
|
||||
// ipRules returns the appropriate list of ip rules to be used by Tailscale. See
|
||||
// comments on baseIPRules and udmProIPRules for more details.
|
||||
func ipRules() []netlink.Rule {
|
||||
if distro.Get() == distro.UDMPro {
|
||||
return udmProIPRules
|
||||
}
|
||||
return baseIPRules
|
||||
}
|
||||
|
||||
// justAddIPRules adds policy routing rule without deleting any first.
|
||||
func (r *linuxRouter) justAddIPRules() error {
|
||||
if !r.ipRuleAvailable {
|
||||
|
@ -1163,7 +1193,7 @@ func (r *linuxRouter) justAddIPRules() error {
|
|||
var errAcc error
|
||||
for _, family := range r.addrFamilies() {
|
||||
|
||||
for _, ru := range ipRules {
|
||||
for _, ru := range ipRules() {
|
||||
// Note: r is a value type here; safe to mutate it.
|
||||
ru.Family = family.netlinkInt()
|
||||
if ru.Mark != 0 {
|
||||
|
@ -1192,7 +1222,7 @@ func (r *linuxRouter) addIPRulesWithIPCommand() error {
|
|||
rg := newRunGroup(nil, r.cmd)
|
||||
|
||||
for _, family := range r.addrFamilies() {
|
||||
for _, rule := range ipRules {
|
||||
for _, rule := range ipRules() {
|
||||
args := []string{
|
||||
"ip", family.dashArg(),
|
||||
"rule", "add",
|
||||
|
@ -1240,7 +1270,7 @@ func (r *linuxRouter) delIPRules() error {
|
|||
}
|
||||
var errAcc error
|
||||
for _, family := range r.addrFamilies() {
|
||||
for _, ru := range ipRules {
|
||||
for _, ru := range ipRules() {
|
||||
// Note: r is a value type here; safe to mutate it.
|
||||
// When deleting rules, we want to be a bit specific (mention which
|
||||
// table we were routing to) but not *too* specific (fwmarks, etc).
|
||||
|
@ -1283,7 +1313,7 @@ func (r *linuxRouter) delIPRulesWithIPCommand() error {
|
|||
// That leaves us some flexibility to change these values in later
|
||||
// versions without having ongoing hacks for every possible
|
||||
// combination.
|
||||
for _, rule := range ipRules {
|
||||
for _, rule := range ipRules() {
|
||||
args := []string{
|
||||
"ip", family.dashArg(),
|
||||
"rule", "del",
|
||||
|
|
Loading…
Reference in New Issue