Skip to content

Commit

Permalink
Fix port mapping (metalbear-co#2061)
Browse files Browse the repository at this point in the history
* Fixed 'listen' detour

* Added integration test

* Added test build to CI

* Added changelog entry

* Fix existing tests

* Format
  • Loading branch information
Razz4780 authored Nov 8, 2023
1 parent ce39d46 commit 62ceb1a
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 7 deletions.
6 changes: 6 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,9 @@ jobs:
- run: |
cd mirrord/layer/tests/apps/issue1458portnot53
rustc issue1458portnot53.rs --out-dir target
- run: |
cd mirrord/layer/tests/apps/issue2058
rustc issue2058.rs --out-dir target
# For the `java_temurin_sip` test.
- uses: sdkman/sdkman-action@b1f9b696c79148b66d3d3a06f7ea801820318d0f
id: sdkman
Expand Down Expand Up @@ -350,6 +353,9 @@ jobs:
- run: |
cd mirrord/layer/tests/apps/issue1458portnot53
rustc issue1458portnot53.rs --out-dir target
- run: |
cd mirrord/layer/tests/apps/issue2058
rustc issue2058.rs --out-dir target
- uses: actions/setup-go@v4
with:
go-version: "1.18"
Expand Down
1 change: 1 addition & 0 deletions changelog.d/2058.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed `port_mapping` feature.
17 changes: 12 additions & 5 deletions mirrord/layer/src/socket/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,11 +254,13 @@ pub(super) fn listen(sockfd: RawFd, backlog: c_int) -> Detour<i32> {
.bypass(Bypass::LocalFdNotFound(sockfd))?
};

if matches!(crate::setup().incoming_config().mode, IncomingMode::Off) {
let setup = crate::setup();

if matches!(setup.incoming_config().mode, IncomingMode::Off) {
return Detour::Bypass(Bypass::DisabledIncoming);
}

if crate::setup().targetless() {
if setup.targetless() {
warn!(
"Listening while running targetless. A targetless agent is not exposed by \
any service. Therefore, letting this port bind happen locally instead of on the \
Expand All @@ -281,11 +283,16 @@ pub(super) fn listen(sockfd: RawFd, backlog: c_int) -> Detour<i32> {
Err(error)?
}

let mapped_port = setup
.incoming_config()
.port_mapping
.get_by_left(&requested_address.port())
.copied()
.unwrap_or_else(|| requested_address.port());

common::make_proxy_request_with_response(PortSubscribe {
listening_on: address,
subscription: crate::setup()
.incoming_mode()
.subscription(requested_address.port()),
subscription: setup.incoming_mode().subscription(mapped_port),
})??;

// this log message is expected by some E2E tests
Expand Down
13 changes: 13 additions & 0 deletions mirrord/layer/tests/apps/issue2058/issue2058.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use std::{net::TcpListener, io::Read};

const LISTEN_ON: &'static str = "0.0.0.0:9999";
const EXPECTED_MESSAGE: &'static [u8] = b"HELLO";

fn main() {
let listener = TcpListener::bind(LISTEN_ON).unwrap();
let (mut stream, _peer) = listener.accept().unwrap();

let mut buff = [0_u8; 10];
let bytes_read = stream.read(&mut buff[..]).unwrap();
assert_eq!(&buff[..bytes_read], EXPECTED_MESSAGE);
}
9 changes: 7 additions & 2 deletions mirrord/layer/tests/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,7 @@ pub enum Application {
RustListenPorts,
Fork,
OpenFile,
RustIssue2058,
// For running applications with the executable and arguments determined at runtime.
DynamicApp(String, Vec<String>),
}
Expand Down Expand Up @@ -785,7 +786,8 @@ impl Application {
"{}/{}",
env!("CARGO_MANIFEST_DIR"),
"tests/apps/open_file/out.c_test_app",
), // String::from("tests/apps/open_file/out.c_test_app"),
),
Application::RustIssue2058 => String::from("tests/apps/issue2058/target/issue2058"),
Application::DynamicApp(exe, _) => exe.clone(),
}
}
Expand Down Expand Up @@ -874,6 +876,7 @@ impl Application {
| Application::Go19SelfOpen
| Application::Go19DirBypass
| Application::Go20DirBypass
| Application::RustIssue2058
| Application::OpenFile => vec![],
Application::RustOutgoingUdp => ["--udp", RUST_OUTGOING_LOCAL, RUST_OUTGOING_PEERS]
.into_iter()
Expand All @@ -896,7 +899,8 @@ impl Application {
| Application::NodeHTTP
| Application::RustIssue1054
| Application::PythonFlaskHTTP => 80,
Application::PythonFastApiHTTP => 9999,
// mapped from 9999 in `configs/port_mapping.json`
Application::PythonFastApiHTTP => 1234,
Application::RustIssue1123 => 41222,
Application::PythonListen => 21232,
Application::PythonDontLoad
Expand Down Expand Up @@ -941,6 +945,7 @@ impl Application {
| Application::OpenFile
| Application::DynamicApp(..) => unimplemented!("shouldn't get here"),
Application::PythonSelfConnect => 1337,
Application::RustIssue2058 => 1234,
}
}

Expand Down
34 changes: 34 additions & 0 deletions mirrord/layer/tests/port_mapping.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#![feature(assert_matches)]
#![warn(clippy::indexing_slicing)]

use std::{path::PathBuf, time::Duration};

use rstest::rstest;

mod common;
pub use common::*;

#[rstest]
#[tokio::test]
#[timeout(Duration::from_secs(20))]
async fn port_mapping(
#[values(Application::RustIssue2058)] application: Application,
dylib_path: &PathBuf,
config_dir: &PathBuf,
) {
let (mut test_process, mut intproxy) = application
.start_process_with_layer_and_port(
dylib_path,
vec![],
Some(config_dir.join("port_mapping.json").to_str().unwrap()),
)
.await;

println!("Application subscribed to port, sending data.");

intproxy
.send_connection_then_data("HELLO", application.get_app_port())
.await;

test_process.wait_assert_success().await;
}

0 comments on commit 62ceb1a

Please sign in to comment.