diff --git a/client/tailscale/localclient.go b/client/tailscale/localclient.go index 73e93dfbb..7b99fc61e 100644 --- a/client/tailscale/localclient.go +++ b/client/tailscale/localclient.go @@ -1332,6 +1332,15 @@ func (lc *LocalClient) DebugDERPRegion(ctx context.Context, regionIDOrCode strin return decodeJSON[*ipnstate.DebugDERPRegionReport](body) } +// DebugPacketFilterRules returns the packet filter rules for the current device. +func (lc *LocalClient) DebugPacketFilterRules(ctx context.Context) ([]tailcfg.FilterRule, error) { + body, err := lc.send(ctx, "POST", "/localapi/v0/debug-packet-filter-rules", 200, nil) + if err != nil { + return nil, fmt.Errorf("error %w: %s", err, body) + } + return decodeJSON[[]tailcfg.FilterRule](body) +} + // DebugSetExpireIn marks the current node key to expire in d. // // This is meant primarily for debug and testing. diff --git a/client/web/src/components/login-toggle.tsx b/client/web/src/components/login-toggle.tsx index f3ed08be2..880437b5b 100644 --- a/client/web/src/components/login-toggle.tsx +++ b/client/web/src/components/login-toggle.tsx @@ -8,6 +8,7 @@ import { ReactComponent as Eye } from "src/assets/icons/eye.svg" import { ReactComponent as User } from "src/assets/icons/user.svg" import { AuthResponse, AuthType } from "src/hooks/auth" import { NodeData } from "src/hooks/node-data" +import Button from "src/ui/button" import Popover from "src/ui/popover" import ProfilePic from "src/ui/profile-pic" @@ -140,44 +141,68 @@ function LoginPopoverContent({ {!auth.canManageNode ? "Viewing" : "Managing"} {auth.viewerIdentity && ` as ${auth.viewerIdentity.loginName}`} - {!auth.canManageNode && - (!auth.viewerIdentity || auth.authNeeded === AuthType.tailscale ? ( - <> -
- {auth.viewerIdentity ? ( + {!auth.canManageNode && ( + <> + {!auth.viewerIdentity ? ( + // User is not connected over Tailscale. + // These states are only possible on the login client. + <> + {!canConnectOverTS ? ( <> - To make changes, sign in to confirm your identity. This extra - step helps us keep your device secure. +
+ {!node.ACLAllowsAnyIncomingTraffic ? ( + // Tailnet ACLs don't allow access. + <> + The current tailnet policy file does not allow + connecting to this device. + > + ) : ( + // ACLs allow access, but user can't connect. + <> + Cannot access this device's Tailscale IP. Make sure you + are connected to your tailnet, and that your policy file + allows access. + > + )}{" "} + + Learn more → + +
> ) : ( + // User can connect to Tailcale IP; sign in when ready. <> - You can see most of this device's details. To make changes, - you need to sign in. ++ You can see most of this device's details. To make changes, + you need to sign in. +
++ To make changes, sign in to confirm your identity. This extra + step helps us keep your device secure. +
++ You don’t have permission to make changes to this device, but you + can view most of its details.
- - > - ) : ( -- You don’t have permission to make changes to this device, but you - can view most of its details. -
- ))} + )} + > + )} {auth.viewerIdentity && ( <>