cli: allow public port forwarding via tunnels (#209489)

This commit is contained in:
Connor Peet 2024-04-03 15:28:00 -07:00 committed by GitHub
parent 0f13661a91
commit 8558da1335
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 28 additions and 11 deletions

View file

@ -498,7 +498,12 @@ fn get_connection_token(tunnel: &ActiveTunnel) -> String {
let mut hash = Sha256::new();
hash.update(tunnel.id.as_bytes());
let result = hash.finalize();
b64::URL_SAFE_NO_PAD.encode(result)
let mut result = b64::URL_SAFE_NO_PAD.encode(result);
if result.starts_with('-') {
result.insert(0, 'a'); // avoid arg parsing issue
}
result
}
async fn serve_with_csa(

View file

@ -10,7 +10,7 @@ use crate::options::Quality;
use crate::rpc::{MaybeSync, RpcBuilder, RpcCaller, RpcDispatcher};
use crate::self_update::SelfUpdate;
use crate::state::LauncherPaths;
use crate::tunnels::protocol::{HttpRequestParams, METHOD_CHALLENGE_ISSUE};
use crate::tunnels::protocol::{HttpRequestParams, PortPrivacy, METHOD_CHALLENGE_ISSUE};
use crate::tunnels::socket_signal::CloseReason;
use crate::update_service::{Platform, Release, TargetKind, UpdateService};
use crate::util::command::new_tokio_command;
@ -1077,8 +1077,16 @@ async fn handle_forward(
let port_forwarding = port_forwarding
.as_ref()
.ok_or(CodeError::PortForwardingNotAvailable)?;
info!(log, "Forwarding port {}", params.port);
let uri = port_forwarding.forward(params.port).await?;
info!(
log,
"Forwarding port {} (public={})", params.port, params.public
);
let privacy = match params.public {
true => PortPrivacy::Public,
false => PortPrivacy::Private,
};
let uri = port_forwarding.forward(params.port, privacy).await?;
Ok(ForwardResult { uri })
}

View file

@ -968,7 +968,6 @@ impl ActiveTunnelManager {
}
/// Adds a port for TCP/IP forwarding.
#[allow(dead_code)] // todo: port forwarding
pub async fn add_port_tcp(
&self,
port_number: u16,

View file

@ -15,7 +15,7 @@ use crate::{
use super::{dev_tunnels::ActiveTunnel, protocol::PortPrivacy};
pub enum PortForwardingRec {
Forward(u16, oneshot::Sender<Result<String, AnyError>>),
Forward(u16, PortPrivacy, oneshot::Sender<Result<String, AnyError>>),
Unforward(u16, oneshot::Sender<Result<(), AnyError>>),
}
@ -54,8 +54,9 @@ impl PortForwardingProcessor {
/// Processes the incoming forwarding request.
pub async fn process(&mut self, req: PortForwardingRec, tunnel: &mut ActiveTunnel) {
match req {
PortForwardingRec::Forward(port, tx) => {
tx.send(self.process_forward(port, tunnel).await).ok();
PortForwardingRec::Forward(port, privacy, tx) => {
tx.send(self.process_forward(port, privacy, tunnel).await)
.ok();
}
PortForwardingRec::Unforward(port, tx) => {
tx.send(self.process_unforward(port, tunnel).await).ok();
@ -80,6 +81,7 @@ impl PortForwardingProcessor {
async fn process_forward(
&mut self,
port: u16,
privacy: PortPrivacy,
tunnel: &mut ActiveTunnel,
) -> Result<String, AnyError> {
if port == CONTROL_PORT {
@ -87,7 +89,7 @@ impl PortForwardingProcessor {
}
if !self.forwarded.contains(&port) {
tunnel.add_port_tcp(port, PortPrivacy::Private).await?;
tunnel.add_port_tcp(port, privacy).await?;
self.forwarded.insert(port);
}
@ -101,9 +103,9 @@ pub struct PortForwarding {
}
impl PortForwarding {
pub async fn forward(&self, port: u16) -> Result<String, AnyError> {
pub async fn forward(&self, port: u16, privacy: PortPrivacy) -> Result<String, AnyError> {
let (tx, rx) = oneshot::channel();
let req = PortForwardingRec::Forward(port, tx);
let req = PortForwardingRec::Forward(port, privacy, tx);
if self.tx.send(req).await.is_err() {
return Err(ServerHasClosed().into());

View file

@ -47,6 +47,8 @@ pub struct HttpHeadersParams {
#[derive(Deserialize, Debug)]
pub struct ForwardParams {
pub port: u16,
#[serde(default)]
pub public: bool,
}
#[derive(Deserialize, Debug)]

View file

@ -82,6 +82,7 @@ export async function activate(context: vscode.ExtensionContext) {
{
tunnelFeatures: {
elevation: false,
protocol: false,
privacyOptions: [
{ themeIcon: 'globe', id: TunnelPrivacyId.Public, label: vscode.l10n.t('Public') },
{ themeIcon: 'lock', id: TunnelPrivacyId.Private, label: vscode.l10n.t('Private') },