diff --git a/src/vs/base/node/ports.ts b/src/vs/base/node/ports.ts index 6ecdc71019c..9d3a8bdcfe1 100644 --- a/src/vs/base/node/ports.ts +++ b/src/vs/base/node/ports.ts @@ -63,6 +63,90 @@ function doFindFreePort(startPort: number, giveUpAfter: number, stride: number, client.connect(startPort, '127.0.0.1'); } +// Reference: https://chromium.googlesource.com/chromium/src.git/+/refs/heads/main/net/base/port_util.cc#56 +export const BROWSER_RESTRICTED_PORTS: any = { + 1: true, // tcpmux + 7: true, // echo + 9: true, // discard + 11: true, // systat + 13: true, // daytime + 15: true, // netstat + 17: true, // qotd + 19: true, // chargen + 20: true, // ftp data + 21: true, // ftp access + 22: true, // ssh + 23: true, // telnet + 25: true, // smtp + 37: true, // time + 42: true, // name + 43: true, // nicname + 53: true, // domain + 69: true, // tftp + 77: true, // priv-rjs + 79: true, // finger + 87: true, // ttylink + 95: true, // supdup + 101: true, // hostriame + 102: true, // iso-tsap + 103: true, // gppitnp + 104: true, // acr-nema + 109: true, // pop2 + 110: true, // pop3 + 111: true, // sunrpc + 113: true, // auth + 115: true, // sftp + 117: true, // uucp-path + 119: true, // nntp + 123: true, // NTP + 135: true, // loc-srv /epmap + 137: true, // netbios + 139: true, // netbios + 143: true, // imap2 + 161: true, // snmp + 179: true, // BGP + 389: true, // ldap + 427: true, // SLP (Also used by Apple Filing Protocol) + 465: true, // smtp+ssl + 512: true, // print / exec + 513: true, // login + 514: true, // shell + 515: true, // printer + 526: true, // tempo + 530: true, // courier + 531: true, // chat + 532: true, // netnews + 540: true, // uucp + 548: true, // AFP (Apple Filing Protocol) + 554: true, // rtsp + 556: true, // remotefs + 563: true, // nntp+ssl + 587: true, // smtp (rfc6409) + 601: true, // syslog-conn (rfc3195) + 636: true, // ldap+ssl + 989: true, // ftps-data + 990: true, // ftps + 993: true, // ldap+ssl + 995: true, // pop3+ssl + 1719: true, // h323gatestat + 1720: true, // h323hostcall + 1723: true, // pptp + 2049: true, // nfs + 3659: true, // apple-sasl / PasswordServer + 4045: true, // lockd + 5060: true, // sip + 5061: true, // sips + 6000: true, // X11 + 6566: true, // sane-port + 6665: true, // Alternate IRC [Apple addition] + 6666: true, // Alternate IRC [Apple addition] + 6667: true, // Standard IRC [Apple addition] + 6668: true, // Alternate IRC [Apple addition] + 6669: true, // Alternate IRC [Apple addition] + 6697: true, // IRC + TLS + 10080: true // Amanda +}; + /** * Uses listen instead of connect. Is faster, but if there is another listener on 0.0.0.0 then this will take 127.0.0.1 from that listener. */ diff --git a/src/vs/platform/remote/node/tunnelService.ts b/src/vs/platform/remote/node/tunnelService.ts index 2a6c75f4532..322b743d2c9 100644 --- a/src/vs/platform/remote/node/tunnelService.ts +++ b/src/vs/platform/remote/node/tunnelService.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as net from 'net'; -import { findFreePortFaster } from 'vs/base/node/ports'; +import { BROWSER_RESTRICTED_PORTS, findFreePortFaster } from 'vs/base/node/ports'; import { NodeSocket } from 'vs/base/parts/ipc/node/ipc.net'; import { nodeSocketFactory } from 'vs/platform/remote/node/nodeSocketFactory'; @@ -18,8 +18,18 @@ import { AbstractTunnelService, isAllInterfaces, ISharedTunnelsService as IShare import { ISignService } from 'vs/platform/sign/common/sign'; async function createRemoteTunnel(options: IConnectionOptions, defaultTunnelHost: string, tunnelRemoteHost: string, tunnelRemotePort: number, tunnelLocalPort?: number): Promise { - const tunnel = new NodeRemoteTunnel(options, defaultTunnelHost, tunnelRemoteHost, tunnelRemotePort, tunnelLocalPort); - return tunnel.waitForReady(); + let readyTunnel: NodeRemoteTunnel | undefined; + for (let attempts = 3; attempts; attempts--) { + if (readyTunnel) { + readyTunnel.dispose(); + } + const tunnel = new NodeRemoteTunnel(options, defaultTunnelHost, tunnelRemoteHost, tunnelRemotePort, tunnelLocalPort); + readyTunnel = await tunnel.waitForReady(); + if ((tunnelLocalPort && BROWSER_RESTRICTED_PORTS[tunnelLocalPort]) || !BROWSER_RESTRICTED_PORTS[readyTunnel.tunnelLocalPort]) { + break; + } + } + return readyTunnel!; } class NodeRemoteTunnel extends Disposable implements RemoteTunnel {