Compare commits
1 Commits
irbekrm/pr
...
bm/4via6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aa5360a295 |
@@ -474,7 +474,7 @@ func (s *Server) servePostNodeUpdate(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
routes, err := netutil.CalcAdvertiseRoutes(postData.AdvertiseRoutes, postData.AdvertiseExitNode)
|
||||
routes, err := netutil.CalcAdvertiseRoutes(st.TailscaleIPs[0], postData.AdvertiseRoutes, postData.AdvertiseExitNode)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
json.NewEncoder(w).Encode(mi{"error": err.Error()})
|
||||
|
||||
@@ -140,7 +140,7 @@ func runSet(ctx context.Context, args []string) (retErr error) {
|
||||
return err
|
||||
}
|
||||
if maskedPrefs.AdvertiseRoutesSet {
|
||||
maskedPrefs.AdvertiseRoutes, err = calcAdvertiseRoutesForSet(advertiseExitNodeSet, advertiseRoutesSet, curPrefs, setArgs)
|
||||
maskedPrefs.AdvertiseRoutes, err = calcAdvertiseRoutesForSet(st.TailscaleIPs[0], advertiseExitNodeSet, advertiseRoutesSet, curPrefs, setArgs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -174,13 +174,13 @@ func runSet(ctx context.Context, args []string) (retErr error) {
|
||||
// advertiseRoutesSet is whether the --advertise-routes flag was set.
|
||||
// curPrefs is the current Prefs.
|
||||
// setArgs is the parsed command-line arguments.
|
||||
func calcAdvertiseRoutesForSet(advertiseExitNodeSet, advertiseRoutesSet bool, curPrefs *ipn.Prefs, setArgs setArgsT) (routes []netip.Prefix, err error) {
|
||||
func calcAdvertiseRoutesForSet(addrV4 netip.Addr, advertiseExitNodeSet, advertiseRoutesSet bool, curPrefs *ipn.Prefs, setArgs setArgsT) (routes []netip.Prefix, err error) {
|
||||
if advertiseExitNodeSet && advertiseRoutesSet {
|
||||
return netutil.CalcAdvertiseRoutes(setArgs.advertiseRoutes, setArgs.advertiseDefaultRoute)
|
||||
return netutil.CalcAdvertiseRoutes(addrV4, setArgs.advertiseRoutes, setArgs.advertiseDefaultRoute)
|
||||
|
||||
}
|
||||
if advertiseRoutesSet {
|
||||
return netutil.CalcAdvertiseRoutes(setArgs.advertiseRoutes, curPrefs.AdvertisesExitNode())
|
||||
return netutil.CalcAdvertiseRoutes(addrV4, setArgs.advertiseRoutes, curPrefs.AdvertisesExitNode())
|
||||
}
|
||||
if advertiseExitNodeSet {
|
||||
alreadyAdvertisesExitNode := curPrefs.AdvertisesExitNode()
|
||||
|
||||
@@ -228,7 +228,7 @@ func warnf(format string, args ...any) {
|
||||
// function exists for testing and should have no side effects or
|
||||
// outside interactions (e.g. no making Tailscale LocalAPI calls).
|
||||
func prefsFromUpArgs(upArgs upArgsT, warnf logger.Logf, st *ipnstate.Status, goos string) (*ipn.Prefs, error) {
|
||||
routes, err := netutil.CalcAdvertiseRoutes(upArgs.advertiseRoutes, upArgs.advertiseDefaultRoute)
|
||||
routes, err := netutil.CalcAdvertiseRoutes(netip.Addr{}, upArgs.advertiseRoutes, upArgs.advertiseDefaultRoute)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
@@ -283,7 +284,9 @@ func (b *LocalBackend) handleC2NWoL(w http.ResponseWriter, r *http.Request) {
|
||||
http.Error(w, "bad method", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
r.ParseForm()
|
||||
err := r.ParseForm()
|
||||
log.Printf("ParseForm=%v: Form=%q, PostForm=%q", err, r.Form, r.PostForm)
|
||||
|
||||
var macs []net.HardwareAddr
|
||||
for _, macStr := range r.Form["mac"] {
|
||||
mac, err := net.ParseMAC(macStr)
|
||||
|
||||
@@ -8,6 +8,7 @@ package resolver
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -21,6 +22,7 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
"unicode"
|
||||
|
||||
dns "golang.org/x/net/dns/dnsmessage"
|
||||
"tailscale.com/control/controlknobs"
|
||||
@@ -680,17 +682,21 @@ func (r *Resolver) resolveLocal(domain dnsname.FQDN, typ dns.Type) (netip.Addr,
|
||||
// (2022-06-02) to work around an issue in Chrome where it would treat
|
||||
// "http://via-1.1.2.3.4" as a search string instead of a URL. We should rip out
|
||||
// the old format in early 2023.
|
||||
func (r *Resolver) parseViaDomain(domain dnsname.FQDN, typ dns.Type) (netip.Addr, bool) {
|
||||
fqdn := string(domain.WithoutTrailingDot())
|
||||
func (r *Resolver) parseViaDomain(domainFQDN dnsname.FQDN, typ dns.Type) (netip.Addr, bool) {
|
||||
fqdn := string(domainFQDN.WithoutTrailingDot())
|
||||
if typ != dns.TypeAAAA {
|
||||
return netip.Addr{}, false
|
||||
}
|
||||
if len(fqdn) < len("via-X.0.0.0.0") {
|
||||
return netip.Addr{}, false // too short to be valid
|
||||
}
|
||||
r.mu.Lock()
|
||||
hosts := r.hostToIP
|
||||
r.mu.Unlock()
|
||||
|
||||
var siteID string
|
||||
var ip4Str string
|
||||
var prefix uint32
|
||||
switch {
|
||||
case strings.Contains(fqdn, "-via-"):
|
||||
// Format number 3: "192-168-1-2-via-7" or "192-168-1-2-via-7.foo.ts.net."
|
||||
@@ -703,8 +709,24 @@ func (r *Resolver) parseViaDomain(domain dnsname.FQDN, typ dns.Type) (netip.Addr
|
||||
if !ok {
|
||||
return netip.Addr{}, false
|
||||
}
|
||||
siteID = suffix
|
||||
ip4Str = strings.ReplaceAll(v4hyphens, "-", ".")
|
||||
if strings.ContainsFunc(suffix, unicode.IsLetter) {
|
||||
// Advertising a whole LAN case. IPv4 address via a specific named node
|
||||
// ("10-0-0-1-via-appletv.foo.ts.net.") where suffix here is
|
||||
// "appletv" and not a numeric site ID.
|
||||
_, node, _ := strings.Cut(domainFQDN.WithTrailingDot(), "-via-")
|
||||
for _, addr := range hosts[dnsname.FQDN(node)] {
|
||||
if addr.Is4() {
|
||||
a4 := addr.As4()
|
||||
prefix = binary.BigEndian.Uint32(a4[:])
|
||||
}
|
||||
}
|
||||
if prefix == 0 {
|
||||
return netip.Addr{}, false
|
||||
}
|
||||
} else {
|
||||
siteID = suffix
|
||||
}
|
||||
case strings.HasPrefix(fqdn, "via-"):
|
||||
firstDot := strings.Index(fqdn, ".")
|
||||
if firstDot < 0 {
|
||||
@@ -730,13 +752,16 @@ func (r *Resolver) parseViaDomain(domain dnsname.FQDN, typ dns.Type) (netip.Addr
|
||||
return netip.Addr{}, false // badly formed, don't respond
|
||||
}
|
||||
|
||||
prefix, err := strconv.ParseUint(siteID, 0, 32)
|
||||
if err != nil {
|
||||
return netip.Addr{}, false // badly formed, don't respond
|
||||
if prefix == 0 {
|
||||
prefix64, err := strconv.ParseUint(siteID, 0, 32)
|
||||
if err != nil {
|
||||
return netip.Addr{}, false // badly formed, don't respond
|
||||
}
|
||||
prefix = uint32(prefix64)
|
||||
}
|
||||
|
||||
// MapVia will never error when given an IPv4 netip.Prefix.
|
||||
out, _ := tsaddr.MapVia(uint32(prefix), netip.PrefixFrom(ip4, ip4.BitLen()))
|
||||
out, _ := tsaddr.MapVia(prefix, netip.PrefixFrom(ip4, ip4.BitLen()))
|
||||
return out.Addr(), true
|
||||
}
|
||||
|
||||
|
||||
@@ -32,8 +32,9 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
testipv4 = netip.MustParseAddr("1.2.3.4")
|
||||
testipv6 = netip.MustParseAddr("0001:0203:0405:0607:0809:0a0b:0c0d:0e0f")
|
||||
testipv4 = netip.MustParseAddr("1.2.3.4")
|
||||
test3ipv4 = netip.MustParseAddr("5.6.7.8")
|
||||
testipv6 = netip.MustParseAddr("0001:0203:0405:0607:0809:0a0b:0c0d:0e0f")
|
||||
|
||||
testipv4Arpa = dnsname.FQDN("4.3.2.1.in-addr.arpa.")
|
||||
testipv6Arpa = dnsname.FQDN("f.0.e.0.d.0.c.0.b.0.a.0.9.0.8.0.7.0.6.0.5.0.4.0.3.0.2.0.1.0.0.0.ip6.arpa.")
|
||||
@@ -43,8 +44,9 @@ var (
|
||||
|
||||
var dnsCfg = Config{
|
||||
Hosts: map[dnsname.FQDN][]netip.Addr{
|
||||
"test1.ipn.dev.": {testipv4},
|
||||
"test2.ipn.dev.": {testipv6},
|
||||
"test1.ipn.dev.": {testipv4},
|
||||
"test2.ipn.dev.": {testipv6},
|
||||
"test3.foo.ts.net.": {test3ipv4},
|
||||
},
|
||||
LocalDomains: []dnsname.FQDN{"ipn.dev.", "3.2.1.in-addr.arpa.", "1.0.0.0.ip6.arpa."},
|
||||
}
|
||||
@@ -352,7 +354,6 @@ func TestResolveLocal(t *testing.T) {
|
||||
|
||||
// Hyphenated 4via6 format.
|
||||
// Without any suffix domain:
|
||||
{"via_form3_hex_bare", dnsname.FQDN("1-2-3-4-via-0xff."), dns.TypeAAAA, netip.MustParseAddr("fd7a:115c:a1e0:b1a:0:ff:1.2.3.4"), dns.RCodeSuccess},
|
||||
{"via_form3_dec_bare", dnsname.FQDN("1-2-3-4-via-1."), dns.TypeAAAA, netip.MustParseAddr("fd7a:115c:a1e0:b1a:0:1:1.2.3.4"), dns.RCodeSuccess},
|
||||
// With a Tailscale domain:
|
||||
{"via_form3_dec_ts.net", dnsname.FQDN("1-2-3-4-via-1.foo.ts.net."), dns.TypeAAAA, netip.MustParseAddr("fd7a:115c:a1e0:b1a:0:1:1.2.3.4"), dns.RCodeSuccess},
|
||||
@@ -361,6 +362,8 @@ func TestResolveLocal(t *testing.T) {
|
||||
// suffixes are currently hard-coded and not plumbed via the netmap)
|
||||
{"via_form3_dec_example.com", dnsname.FQDN("1-2-3-4-via-1.example.com."), dns.TypeAAAA, netip.Addr{}, dns.RCodeRefused},
|
||||
{"via_form3_dec_examplets.net", dnsname.FQDN("1-2-3-4-via-1.examplets.net."), dns.TypeAAAA, netip.Addr{}, dns.RCodeRefused},
|
||||
|
||||
{"via_lan", dnsname.FQDN("10-20-30-40-via-test3.foo.ts.net."), dns.TypeAAAA, netip.MustParseAddr("fd7a:115c:a1e0:b1a:0506:0708:10.20.30.40"), dns.RCodeSuccess},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
||||
@@ -41,12 +41,25 @@ func validateViaPrefix(ipp netip.Prefix) error {
|
||||
// CalcAdvertiseRoutes calculates the requested routes to be advertised by a node.
|
||||
// advertiseRoutes is the user-provided, comma-separated list of routes (IP addresses or CIDR prefixes) to advertise.
|
||||
// advertiseDefaultRoute indicates whether the node should act as an exit node and advertise default routes.
|
||||
func CalcAdvertiseRoutes(advertiseRoutes string, advertiseDefaultRoute bool) ([]netip.Prefix, error) {
|
||||
func CalcAdvertiseRoutes(selfIPv4 netip.Addr, advertiseRoutes string, advertiseDefaultRoute bool) ([]netip.Prefix, error) {
|
||||
routeMap := map[netip.Prefix]bool{}
|
||||
if advertiseRoutes != "" {
|
||||
var default4, default6 bool
|
||||
advroutes := strings.Split(advertiseRoutes, ",")
|
||||
for _, s := range advroutes {
|
||||
if s == "lan-via6" {
|
||||
if !selfIPv4.IsValid() {
|
||||
return nil, fmt.Errorf("cannot advertise lan-via6 route until you're connected to Tailscale")
|
||||
}
|
||||
a4 := selfIPv4.As4()
|
||||
selfSiteID := binary.BigEndian.Uint32(a4[:])
|
||||
for _, pfxStr := range []string{"10.0.0.0/8", "192.168.0.0/16", "172.16.0.0/12"} {
|
||||
pfx := netip.MustParsePrefix(pfxStr)
|
||||
pfx6, _ := tsaddr.MapVia(selfSiteID, pfx)
|
||||
routeMap[pfx6] = true
|
||||
}
|
||||
continue
|
||||
}
|
||||
ipp, err := netip.ParsePrefix(s)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%q is not a valid IP address or CIDR prefix", s)
|
||||
|
||||
Reference in New Issue
Block a user