Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix ERR_UNSAFE_PORT from LensProxy #4558

Merged
merged 3 commits into from
Dec 14, 2021
Merged
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
65 changes: 58 additions & 7 deletions src/main/lens-proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,24 @@ export function isLongRunningRequest(reqUrl: string) {
return getBoolean(url.searchParams, watchParam) || getBoolean(url.searchParams, followParam);
}

/**
* This is the list of ports that chrome considers unsafe to allow HTTP
* conntections to. Because they are the standard ports for processes that are
* too forgiving in the connection types they accept.
*
* If we get one of these ports, the easiest thing to do is to just try again.
*
* Source: https://chromium.googlesource.com/chromium/src.git/+/refs/heads/main/net/base/port_util.cc
*/
const disallowedPorts = new Set([
1, 7, 9, 11, 13, 15, 17, 19, 20, 21, 22, 23, 25, 37, 42, 43, 53, 69, 77, 79,
87, 95, 101, 102, 103, 104, 109, 110, 111, 113, 115, 117, 119, 123, 135, 137,
139, 143, 161, 179, 389, 427, 465, 512, 513, 514, 515, 526, 530, 531, 532,
540, 548, 554, 556, 563, 587, 601, 636, 989, 990, 993, 995, 1719, 1720, 1723,
2049, 3659, 4045, 5060, 5061, 6000, 6566, 6665, 6666, 6667, 6668, 6669, 6697,
10080,
]);

export class LensProxy extends Singleton {
protected origin: string;
protected proxyServer: http.Server;
Expand Down Expand Up @@ -91,12 +109,13 @@ export class LensProxy extends Singleton {
}

/**
* Starts the lens proxy.
* @resolves After the server is listening
* @rejects if there is an error before that happens
* Starts to listen on an OS provided port. Will reject if the server throws
* an error.
*
* Resolves with the port number that was picked
*/
listen(): Promise<void> {
return new Promise<void>((resolve, reject) => {
private attemptToListen(): Promise<number> {
return new Promise<number>((resolve, reject) => {
this.proxyServer.listen(0, "127.0.0.1");

this.proxyServer
Expand All @@ -113,7 +132,7 @@ export class LensProxy extends Singleton {

this.port = port;
appEventBus.emit({ name: "lens-proxy", action: "listen", params: { port }});
resolve();
resolve(port);
})
.once("error", (error) => {
logger.info(`[LENS-PROXY]: Proxy server failed to start: ${error}`);
Expand All @@ -122,8 +141,40 @@ export class LensProxy extends Singleton {
});
}

/**
* Starts the lens proxy.
* @resolves After the server is listening on a good port
* @rejects if there is an error before that happens
*/
async listen(): Promise<void> {
const seenPorts = new Set<number>();

while(true) {
this.proxyServer?.close();
const port = await this.attemptToListen();

if (!disallowedPorts.has(port)) {
// We didn't get a port that would result in an ERR_UNSAFE_PORT error, use it
return;
}

logger.warn(`[LENS-PROXY]: Proxy server has with port known to be considered unsafe to connect to by chrome, restarting...`);

if (seenPorts.has(port)) {
/**
* Assume that if we have seen the port before, then the OS has looped
* through all the ports possible and we will not be able to get a safe
* port.
*/
throw new Error("Failed to start LensProxy due to seeing too many unsafe ports. Please restart Lens.");
} else {
seenPorts.add(port);
}
}
}

close() {
logger.info("Closing proxy server");
logger.info("[LENS-PROXY]: Closing server");
this.proxyServer.close();
this.closed = true;
}
Expand Down