Skip to content
Open
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
7 changes: 7 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"dependencies": {
"@axa-fr/react-oidc": "^7.26.3",
"@dagrejs/dagre": "^1.1.5",
"@novnc/novnc": "^1.7.0",
Comment thread
lixmal marked this conversation as resolved.
"@radix-ui/react-accordion": "^1.2.12",
"@radix-ui/react-checkbox": "^1.3.3",
"@radix-ui/react-collapsible": "^1.1.12",
Expand Down
4 changes: 3 additions & 1 deletion src/app/(dashboard)/peer/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ import { PeerEditIPModal } from "@/modules/peer/PeerEditIPModal";
import { PeerSSHToggle } from "@/modules/peer/PeerSSHToggle";
import { RDPButton } from "@/modules/remote-access/rdp/RDPButton";
import { SSHButton } from "@/modules/remote-access/ssh/SSHButton";
import { VNCButton } from "@/modules/remote-access/vnc/VNCButton";
import { PeerExpirationSettings } from "@/modules/peer/PeerExpirationSettings";

export default function PeerPage() {
Expand Down Expand Up @@ -474,10 +475,11 @@ const PeerOverviewTabContent = () => {
{/* Remote Access Buttons */}
<div>
<Label>Remote Access</Label>
<HelpText>Connect directly to this peer via SSH or RDP.</HelpText>
<HelpText>Connect directly to this peer via SSH, RDP, or VNC.</HelpText>
<div className="flex gap-3">
<SSHButton peer={peer} />
<RDPButton peer={peer} />
<VNCButton peer={peer} />
</div>
</div>
</div>
Expand Down
29 changes: 12 additions & 17 deletions src/app/(remote-access)/peer/rdp/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
"use client";

import { notify } from "@components/Notification";
import { sendErrorNotification } from "@/modules/remote-access/errorNotification";
import FullScreenLoading from "@components/ui/FullScreenLoading";
import { IconCircleX } from "@tabler/icons-react";
import useFetchApi from "@utils/api";
import { Loader2Icon } from "lucide-react";
import React, { useCallback, useEffect, useRef, useState } from "react";
Expand All @@ -22,7 +21,7 @@ import {
import { cn } from "@utils/helpers";

export default function RDPPage() {
const { peerId } = useRDPQueryParams();
const { peerId, ipVersion } = useRDPQueryParams();

const {
data: peer,
Expand All @@ -33,7 +32,7 @@ export default function RDPPage() {
return (
<div className={"w-screen h-screen overflow-hidden fixed inset-0"}>
{peerId && peer && !isLoading ? (
<RDPSession key={peer.id} peer={peer} />
<RDPSession key={peer.id} peer={peer} ipVersion={ipVersion} />
) : (
<FullScreenLoading />
)}
Expand All @@ -43,30 +42,25 @@ export default function RDPPage() {

type Props = {
peer: Peer;
ipVersion: string | null;
};

function RDPSession({ peer }: Props) {
function RDPSession({ peer, ipVersion }: Props) {
const client = useNetBirdClient();
const [isNetBirdConnecting, setIsNetBirdConnecting] = useState(false);
const rdp = useRemoteDesktop(client);
const [credentialsModal, setCredentialsModal] = useState(true);
const [credentials, setCredentials] = useState<RDPCredentials | null>(null);
const connected = useRef(false);

// Dial the IPv6 address when IPv6 was selected, IPv4 otherwise.
const rdpHost =
credentials?.ipVersion === "6" && peer.ipv6 ? peer.ipv6 : peer.ip;

useEffect(() => {
document.title = `${peer.name} - ${peer.ip} - RDP`;
}, [peer.ip, peer.name, connected, rdp]);

const sendErrorNotification = (title: string, message: string) => {
notify({
title: title,
description: message,
icon: <IconCircleX size={24} />,
backgroundColor: "bg-red-500",
duration: 10000,
});
};

/**
* Reset the RDP session state but keep the NetBird client connected,
* so a retry does not pay the full engine reconnect.
Expand Down Expand Up @@ -131,7 +125,7 @@ function RDPSession({ peer }: Props) {
if (!credentials) return;
try {
const result = await rdp.connect({
hostname: peer.ip,
hostname: rdpHost,
port: credentials.port,
username: credentials.username,
password: credentials.password,
Expand All @@ -148,7 +142,7 @@ function RDPSession({ peer }: Props) {
setCredentialsModal(true);
await reset();
}
}, [credentials, peer.ip, rdp, reset]);
}, [credentials, rdpHost, rdp, reset]);

/**
* Establish RDP session when NetBird connection is ready
Expand Down Expand Up @@ -207,6 +201,7 @@ function RDPSession({ peer }: Props) {
peer={peer}
onConnect={connect}
loading={isLoading}
initialIpVersion={ipVersion}
/>

{/* Certificate Modal */}
Expand Down
6 changes: 3 additions & 3 deletions src/app/(remote-access)/peer/ssh/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ function SSHTerminal({ username, port, peer, ipVersion }: Props) {
const isClientDisconnected = client.status === NetBirdStatus.DISCONNECTED;
const isClientConnecting = client.status === NetBirdStatus.CONNECTING;

// Use the FQDN when an IP version is specified so the dialer resolves to the correct address family.
const sshHost = ipVersion ? peer.dns_label || peer.ip : peer.ip;
// Dial the IPv6 address when ip_version=6 is requested, IPv4 otherwise.
const sshHost = ipVersion === "6" && peer.ipv6 ? peer.ipv6 : peer.ip;

useEffect(() => {
document.title = `${username}@${sshHost} - ${peer.hostname}`;
Expand Down Expand Up @@ -178,7 +178,7 @@ function SSHTerminal({ username, port, peer, ipVersion }: Props) {
<>
{session && <Terminal session={session} onClose={disconnect} />}
{!isSSHConnected && (
<LoadingMessage message={`Connecting to ${username}@${peer.ip}...`} />
<LoadingMessage message={`Connecting to ${username}@${sshHost}...`} />
)}
</>
);
Expand Down
Loading
Loading