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
59 changes: 59 additions & 0 deletions lib/teleterm/vnet/service.go
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's easy enough for me to understand the changes in this file since I have the required context. But I think for other reviewers it'd have helped if the changes in lib/teleterm/vnet supporting diag checks on Windows were in a separate commit from the routeconflict Windows implementation.

Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,65 @@ func (s *Service) GetServiceInfo(ctx context.Context, _ *api.GetServiceInfoReque
}, nil
}

// RunDiagnostics runs a set of heuristics to determine if VNet actually works
// on the device. It requires VNet to be started.
func (s *Service) RunDiagnostics(ctx context.Context, req *api.RunDiagnosticsRequest) (*api.RunDiagnosticsResponse, error) {
s.mu.Lock()
defer s.mu.Unlock()

if s.status != statusRunning {
return nil, trace.CompareFailed("VNet is not running")
}

if s.networkStackInfo.InterfaceName == "" {
return nil, trace.BadParameter("no interface name, this is a bug")
}

if s.networkStackInfo.Ipv6Prefix == "" {
return nil, trace.BadParameter("no IPv6 prefix, this is a bug")
}

nsa := &diagv1.NetworkStackAttempt{}
if ns, err := s.getNetworkStack(ctx); err != nil {
nsa.Status = diagv1.CheckAttemptStatus_CHECK_ATTEMPT_STATUS_ERROR
nsa.Error = err.Error()
} else {
nsa.Status = diagv1.CheckAttemptStatus_CHECK_ATTEMPT_STATUS_OK
nsa.NetworkStack = ns
}

diagChecks, err := s.platformDiagChecks(ctx)
Comment thread
nklaassen marked this conversation as resolved.
if err != nil {
return nil, trace.Wrap(err)
}

report, err := diag.GenerateReport(ctx, diag.ReportPrerequisites{
Clock: s.cfg.Clock,
NetworkStackAttempt: nsa,
DiagChecks: diagChecks,
})
if err != nil {
return nil, trace.Wrap(err)
}

return &api.RunDiagnosticsResponse{
Report: report,
}, nil
}

func (s *Service) getNetworkStack(ctx context.Context) (*diagv1.NetworkStack, error) {
unifiedClusterConfig, err := s.vnetProcess.GetUnifiedClusterConfigProvider().GetUnifiedClusterConfig(ctx)
if err != nil {
return nil, trace.Wrap(err)
}
return &diagv1.NetworkStack{
InterfaceName: s.networkStackInfo.InterfaceName,
Ipv6Prefix: s.networkStackInfo.Ipv6Prefix,
Ipv4CidrRanges: unifiedClusterConfig.IPv4CidrRanges,
DnsZones: unifiedClusterConfig.AllDNSZones(),
}, nil
}

func (s *Service) stopLocked() error {
if s.status == statusClosed {
return trace.CompareFailed("VNet service has been closed")
Expand Down
60 changes: 4 additions & 56 deletions lib/teleterm/vnet/service_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,38 +21,10 @@ import (

"github.com/gravitational/trace"

api "github.com/gravitational/teleport/gen/proto/go/teleport/lib/teleterm/vnet/v1"
diagv1 "github.com/gravitational/teleport/gen/proto/go/teleport/lib/vnet/diag/v1"
"github.com/gravitational/teleport/lib/vnet/diag"
)

// RunDiagnostics runs a set of heuristics to determine if VNet actually works on the device, that
// is receives network traffic and DNS queries. RunDiagnostics requires VNet to be started.
func (s *Service) RunDiagnostics(ctx context.Context, req *api.RunDiagnosticsRequest) (*api.RunDiagnosticsResponse, error) {
s.mu.Lock()
defer s.mu.Unlock()

if s.status != statusRunning {
return nil, trace.CompareFailed("VNet is not running")
}

if s.networkStackInfo.InterfaceName == "" {
return nil, trace.BadParameter("no interface name, this is a bug")
}

if s.networkStackInfo.Ipv6Prefix == "" {
return nil, trace.BadParameter("no IPv6 prefix, this is a bug")
}

nsa := &diagv1.NetworkStackAttempt{}
if ns, err := s.getNetworkStack(ctx); err != nil {
nsa.Status = diagv1.CheckAttemptStatus_CHECK_ATTEMPT_STATUS_ERROR
nsa.Error = err.Error()
} else {
nsa.Status = diagv1.CheckAttemptStatus_CHECK_ATTEMPT_STATUS_OK
nsa.NetworkStack = ns
}

func (s *Service) platformDiagChecks(ctx context.Context) ([]diag.DiagCheck, error) {
routeConflictDiag, err := diag.NewRouteConflictDiag(&diag.RouteConflictConfig{
VnetIfaceName: s.networkStackInfo.InterfaceName,
Routing: &diag.DarwinRouting{},
Expand All @@ -69,32 +41,8 @@ func (s *Service) RunDiagnostics(ctx context.Context, req *api.RunDiagnosticsReq
return nil, trace.Wrap(err)
}

report, err := diag.GenerateReport(ctx, diag.ReportPrerequisites{
Clock: s.cfg.Clock,
NetworkStackAttempt: nsa,
DiagChecks: []diag.DiagCheck{
routeConflictDiag,
sshDiag,
},
})
if err != nil {
return nil, trace.Wrap(err)
}

return &api.RunDiagnosticsResponse{
Report: report,
}, nil
}

func (s *Service) getNetworkStack(ctx context.Context) (*diagv1.NetworkStack, error) {
unifiedClusterConfig, err := s.vnetProcess.GetUnifiedClusterConfigProvider().GetUnifiedClusterConfig(ctx)
if err != nil {
return nil, trace.Wrap(err)
}
return &diagv1.NetworkStack{
InterfaceName: s.networkStackInfo.InterfaceName,
Ipv6Prefix: s.networkStackInfo.Ipv6Prefix,
Ipv4CidrRanges: unifiedClusterConfig.IPv4CidrRanges,
DnsZones: unifiedClusterConfig.AllDNSZones(),
return []diag.DiagCheck{
routeConflictDiag,
sshDiag,
}, nil
}
29 changes: 29 additions & 0 deletions lib/teleterm/vnet/service_other.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Teleport
// Copyright (C) 2025 Gravitational, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

//go:build !darwin && !windows

package vnet

import (
"context"

"github.com/gravitational/teleport/lib/vnet/diag"
)

func (s *Service) platformDiagChecks(ctx context.Context) ([]diag.DiagCheck, error) {
return nil, nil
}
48 changes: 48 additions & 0 deletions lib/teleterm/vnet/service_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Teleport
// Copyright (C) 2025 Gravitational, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

package vnet

import (
"context"

"github.com/gravitational/trace"

"github.com/gravitational/teleport/lib/vnet/diag"
)

func (s *Service) platformDiagChecks(ctx context.Context) ([]diag.DiagCheck, error) {
routeConflictDiag, err := diag.NewRouteConflictDiag(&diag.RouteConflictConfig{
VnetIfaceName: s.networkStackInfo.InterfaceName,
Routing: &diag.WindowsRouting{},
Interfaces: &diag.NetInterfaces{},
})
if err != nil {
return nil, trace.Wrap(err)
}

sshDiag, err := diag.NewSSHDiag(&diag.SSHConfig{
ProfilePath: s.cfg.profilePath,
})
if err != nil {
return nil, trace.Wrap(err)
}

return []diag.DiagCheck{
routeConflictDiag,
sshDiag,
}, nil
}
2 changes: 1 addition & 1 deletion lib/vnet/diag/routeconflict_other.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build !darwin
//go:build !darwin && !windows

// Teleport
// Copyright (C) 2025 Gravitational, Inc.
Expand Down
79 changes: 79 additions & 0 deletions lib/vnet/diag/routeconflict_windows.go
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried it out with Tailscale. It seems like what we report on Windows could be categorized as a false positive. Unlike on macOS, on Windows there's just a few conflicting Tailscale routes, not a whole range.

But I think that's fine, no? Technically maybe it could cause issues with VNet, idk. If the user is bothered with the warning, they can dismiss it in the VNet panel and it won't show up again until they manually run diagnostics.

Report

VNet Diagnostic Report

Created at: 2025-06-18 11:19:13 (Wed, 18 Jun 2025 09:19:13 GMT)
Network interface: TeleportVNet
IPv4 CIDR ranges: 100.64.0.0/10
IPv6 prefix: fd5e:d015:6e86::
DNS zones: company.test, cluster.mirrors.link, leaf.mirrors.link


⚠️ There are network routes in conflict with VNet.

VNet destination Conflicting destination Interface Set up by
100.64.0.0/10 100.78.53.61 Tailscale Tailscale
100.64.0.0/10 100.80.252.65 Tailscale Tailscale
100.64.0.0/10 100.87.112.117 Tailscale Tailscale
100.64.0.0/10 100.95.109.108 Tailscale Tailscale
100.64.0.0/10 100.100.100.100 Tailscale Tailscale
100.64.0.0/10 100.106.203.59 Tailscale Tailscale
$ netstat -rn
===========================================================================
Interface List
  3...........................WireGuard Tunnel
  4...........................Tailscale Tunnel
 11...00 1c 42 a3 34 34 ......Parallels VirtIO Ethernet Adapter
  1...........................Software Loopback Interface 1
===========================================================================

IPv4 Route Table
===========================================================================
Active Routes:
Network Destination        Netmask          Gateway       Interface  Metric
          0.0.0.0          0.0.0.0      192.168.1.1    192.168.1.196     15
       100.64.0.0      255.192.0.0       100.64.0.1                3      6
     100.78.53.61  255.255.255.255         On-link    100.106.203.59      5
    100.80.252.65  255.255.255.255         On-link    100.106.203.59      5
   100.87.112.117  255.255.255.255         On-link    100.106.203.59      5
   100.95.109.108  255.255.255.255         On-link    100.106.203.59      5
  100.100.100.100  255.255.255.255         On-link    100.106.203.59      5
   100.106.203.59  255.255.255.255         On-link    100.106.203.59    261
        127.0.0.0        255.0.0.0         On-link         127.0.0.1    331
        127.0.0.1  255.255.255.255         On-link         127.0.0.1    331
  127.255.255.255  255.255.255.255         On-link         127.0.0.1    331
      192.168.1.0    255.255.255.0         On-link     192.168.1.196    271
    192.168.1.196  255.255.255.255         On-link     192.168.1.196    271
    192.168.1.255  255.255.255.255         On-link     192.168.1.196    271
        224.0.0.0        240.0.0.0         On-link         127.0.0.1    331
        224.0.0.0        240.0.0.0         On-link     192.168.1.196    271
        224.0.0.0        240.0.0.0         On-link                 3    261
  255.255.255.255  255.255.255.255         On-link         127.0.0.1    331
  255.255.255.255  255.255.255.255         On-link     192.168.1.196    271
  255.255.255.255  255.255.255.255         On-link                 3    261
===========================================================================
Persistent Routes:
  None

IPv6 Route Table
===========================================================================
Active Routes:
 If Metric Network Destination      Gateway
  1    331 ::1/128                  On-link
  4      5 fd7a:115c:a1e0::/48      fd7a:115c:a1e0::53
  4      5 fd7a:115c:a1e0::53/128   On-link
  4    261 fd7a:115c:a1e0::d701:cb3b/128
                                    On-link
 11    271 fe80::/64                On-link
  3    261 fe80::/64                On-link
  3    261 fe80::3b0e:5a54:acf1:f746/128
                                    On-link
 11    271 fe80::76b6:a13f:6baf:a727/128
                                    On-link
  1    331 ff00::/8                 On-link
 11    271 ff00::/8                 On-link
  3    261 ff00::/8                 On-link
===========================================================================
Persistent Routes:
  None

$ ipconfig /all

Windows IP Configuration

   Host Name . . . . . . . . . . . . : RAFACIELAK0690
   Primary Dns Suffix  . . . . . . . : 
   Node Type . . . . . . . . . . . . : Hybrid
   IP Routing Enabled. . . . . . . . : No
   WINS Proxy Enabled. . . . . . . . : No
   DNS Suffix Search List. . . . . . : ocelot-paradise.ts.net

Unknown adapter TeleportVNet:

   Connection-specific DNS Suffix  . : 
   Description . . . . . . . . . . . : WireGuard Tunnel
   Physical Address. . . . . . . . . : 
   DHCP Enabled. . . . . . . . . . . : No
   Autoconfiguration Enabled . . . . : Yes
   IPv6 Address. . . . . . . . . . . : fd5e:d015:6e86::1(Tentative) 
   Link-local IPv6 Address . . . . . : fe80::3b0e:5a54:acf1:f746%3(Preferred) 
   IPv4 Address. . . . . . . . . . . : 100.64.0.1(Tentative) 
   Subnet Mask . . . . . . . . . . . : 255.0.0.0
   Default Gateway . . . . . . . . . : 
   NetBIOS over Tcpip. . . . . . . . : Enabled

Unknown adapter Tailscale:

   Connection-specific DNS Suffix  . : ocelot-paradise.ts.net
   Description . . . . . . . . . . . : Tailscale Tunnel
   Physical Address. . . . . . . . . : 
   DHCP Enabled. . . . . . . . . . . : No
   Autoconfiguration Enabled . . . . : Yes
   IPv6 Address. . . . . . . . . . . : fd7a:115c:a1e0::d701:cb3b(Preferred) 
   Link-local IPv6 Address . . . . . : fe80::d8ff:5060:f230:9168%4(Preferred) 
   IPv4 Address. . . . . . . . . . . : 100.106.203.59(Preferred) 
   Subnet Mask . . . . . . . . . . . : 255.255.255.255
   Default Gateway . . . . . . . . . : 
   NetBIOS over Tcpip. . . . . . . . : Disabled
   Connection-specific DNS Suffix Search List :
                                       ocelot-paradise.ts.net

Ethernet adapter Ethernet:

   Connection-specific DNS Suffix  . : 
   Description . . . . . . . . . . . : Parallels VirtIO Ethernet Adapter
   Physical Address. . . . . . . . . : 00-1C-42-A3-34-34
   DHCP Enabled. . . . . . . . . . . : Yes
   Autoconfiguration Enabled . . . . : Yes
   Link-local IPv6 Address . . . . . : fe80::76b6:a13f:6baf:a727%11(Preferred) 
   IPv4 Address. . . . . . . . . . . : 192.168.1.196(Preferred) 
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Lease Obtained. . . . . . . . . . : sroda, 18 czerwca 2025 11:02:04
   Lease Expires . . . . . . . . . . : czwartek, 19 czerwca 2025 11:02:03
   Default Gateway . . . . . . . . . : 192.168.1.1
   DHCP Server . . . . . . . . . . . : 192.168.1.1
   DHCPv6 IAID . . . . . . . . . . . : 83893314
   DHCPv6 Client DUID. . . . . . . . : 00-01-00-01-2A-67-8E-5D-00-1C-42-A3-34-34
   DNS Servers . . . . . . . . . . . : 1.1.1.1
                                       192.168.1.1
   NetBIOS over Tcpip. . . . . . . . : Enabled

$ netsh namespace show effectivepolicy

DNS Effective Name Resolution Policy Table Settings

Note: DirectAccess settings are inactive when this computer is inside a corporate network.


Settings for .leaf.mirrors.link
----------------------------------------------------------------------
Generic (DNS Servers)                   : fd5e:d015:6e86::2
Generic (VPN Trigger)                   : disabled


Settings for .cluster.mirrors.link
----------------------------------------------------------------------
Generic (DNS Servers)                   : fd5e:d015:6e86::2
Generic (VPN Trigger)                   : disabled


Settings for .company.test
----------------------------------------------------------------------
Generic (DNS Servers)                   : fd5e:d015:6e86::2
Generic (VPN Trigger)                   : disabled


Settings for .84.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .83.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .82.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .81.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .80.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .79.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .78.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .77.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .76.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .75.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .74.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .73.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .72.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .71.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .70.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .69.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .68.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .67.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .66.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .65.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .64.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .127.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .126.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .125.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .124.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .123.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .122.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .121.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .120.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .119.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .118.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .117.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .116.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .115.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .114.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .113.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .112.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .111.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .110.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .109.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .108.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .107.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .106.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .105.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .104.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .103.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .102.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .101.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .100.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .0.e.1.a.c.5.1.1.a.7.d.f.ip6.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .ts.net
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .ocelot-paradise.ts.net
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .99.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .98.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .97.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .96.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .95.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .94.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .93.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .92.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .91.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .90.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .89.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .88.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .87.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .86.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled


Settings for .85.100.in-addr.arpa
----------------------------------------------------------------------
Generic (DNS Servers)                   : 100.100.100.100
Generic (VPN Trigger)                   : disabled




⚠️ VNet SSH is not configured.

The user's default SSH configuration file does not include VNet's
generated configuration file and connections to VNet SSH hosts will
not work by default.

File description Path
User OpenSSH config file C:\Users\rav.ssh\config
VNet SSH config file C:\Users\rav\AppData\Roaming\Teleport Connect\tsh\vnet_ssh_config

Ran into an error when executing cat C:\Users\rav.ssh\config:
exit status 1
cat: 'C:\Users\rav.ssh\config': No such file or directory

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's maybe fine until VNet tries to assign an IP to an app that tailscale is already routing for, probably still best to know about the potential conflict and use a different IP range

Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Teleport
// Copyright (C) 2025 Gravitational, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

package diag

import (
"context"
"net/netip"
"os/exec"

"github.com/gravitational/trace"
"golang.org/x/sys/windows"
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
)

var ipv4Broadcast = netip.AddrFrom4([4]byte{255, 255, 255, 255})

// WindowsRouting provides Windows-specific [Routing] implementation used by [RouteConflictDiag].
type WindowsRouting struct{}

// GetRouteDestinations gets routes from the OS and then extracts the only
// information needed from them: the route destination and the index of the
// network interface. It operates solely on IPv4 routes.
func (wr *WindowsRouting) GetRouteDestinations() ([]RouteDest, error) {
rows, err := winipcfg.GetIPForwardTable2(windows.AF_INET)
if err != nil {
return nil, trace.Wrap(err)
}
rds := make([]RouteDest, 0, len(rows))
for _, row := range rows {
prefix := row.DestinationPrefix.Prefix()
addr := prefix.Addr()
if addr.IsLinkLocalMulticast() || addr == ipv4Broadcast {
// All interfaces seem to get a link local multicast and broadcast
// route assigned which would always appear as a conflict, so skip
// them.
continue
}
if prefix.IsSingleIP() {
rds = append(rds, &RouteDestIP{
Addr: addr,
ifaceIndex: int(row.InterfaceIndex),
})
} else {
rds = append(rds, &RouteDestPrefix{
Prefix: prefix,
ifaceIndex: int(row.InterfaceIndex),
})
}
}
return rds, nil
}

func (n *NetInterfaces) interfaceApp(ctx context.Context, ifaceName string) (string, error) {
// Interfaces usually have descriptive names on Windows (the TUN interfaces
// used by VNet and Tailscale do, at least).
return ifaceName, nil
}

func (c *RouteConflictDiag) commands(ctx context.Context) []*exec.Cmd {
return []*exec.Cmd{
exec.CommandContext(ctx, "netstat.exe", "-rn"),
exec.CommandContext(ctx, "ipconfig.exe", "/all"),
exec.CommandContext(ctx, "netsh.exe", "namespace", "show", "effectivepolicy"),
}
}
23 changes: 10 additions & 13 deletions web/packages/teleterm/src/ui/Vnet/VnetConnectionItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,6 @@ const VnetConnectionItemBase = forwardRef<
diagnosticsAttempt,
getDisabledDiagnosticsReason,
showDiagWarningIndicator,
isDiagSupported,
} = useVnetContext();
const { close: closeConnectionsPanel } = useConnectionsContext();
const rootClusterUri = useStoreSelector(
Expand Down Expand Up @@ -259,18 +258,16 @@ const VnetConnectionItemBase = forwardRef<
</ButtonIcon>
)}

{isDiagSupported && (
<ButtonIcon
title={disabledDiagnosticsReason || 'Run diagnostics'}
disabled={!!disabledDiagnosticsReason}
onClick={e => {
e.stopPropagation();
props.runDiagnosticsFromVnetPanel();
}}
>
<icons.ListMagnifyingGlass size={18} />
</ButtonIcon>
)}
<ButtonIcon
title={disabledDiagnosticsReason || 'Run diagnostics'}
disabled={!!disabledDiagnosticsReason}
onClick={e => {
e.stopPropagation();
props.runDiagnosticsFromVnetPanel();
}}
>
<icons.ListMagnifyingGlass size={18} />
</ButtonIcon>
</>
)}

Expand Down
6 changes: 1 addition & 5 deletions web/packages/teleterm/src/ui/Vnet/VnetSliderStep.story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ type StoryProps = {
| 'error'
| 'processing'
| 'processing-with-previous-results';
vnetDiag: boolean;
runDiagnostics: 'success' | 'error' | 'processing';
diagReport: 'ok' | 'issues-found' | 'failed-checks';
isWorkspacePresent: boolean;
Expand All @@ -60,7 +59,6 @@ const defaultArgs: StoryProps = {
clusters: ['teleport.example.com'],
sshConfigured: false,
fetchStatus: 'success',
vnetDiag: true,
runDiagnostics: 'success',
diagReport: 'ok',
isWorkspacePresent: true,
Expand Down Expand Up @@ -117,9 +115,7 @@ const meta: Meta<StoryProps> = {
export default meta;

function VnetSliderStep(props: StoryProps) {
const appContext = new MockAppContext({
platform: props.vnetDiag ? 'darwin' : 'win32',
});
const appContext = new MockAppContext();

if (props.isWorkspacePresent) {
appContext.addRootCluster(makeRootCluster());
Expand Down
Loading
Loading