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(connlib): deterministically route packets in case of overlap #5082

Merged
merged 12 commits into from
May 25, 2024

Conversation

thomaseizinger
Copy link
Member

@thomaseizinger thomaseizinger commented May 22, 2024

Currently, we only consult the IP ranges of our configured resources for the initial connection to a gateway. Once a connection is established, packets are routed based on an IP range associated with that gateway. This is inconsistent and actually causes problems in case the user configures overlapping resources. In particular, adding a resource with an overlapping but narrower IP network range to a client that is already connected to a gateway with an overlapping but wider range will cause all packets for the newly added resource to be routed to the already connected gateway.

To fix this, we consult the IP network table of resources for each packet to figure out, which resource is the most appropriate one. Then, we pick the gateway that is configured for this resource. If we aren't connected to that gateway or if we don't know about a gateway for this resource, we emit a connection intent.

In case the portal wants to use an already connected gateway for that resource, we handle that using the "reuse connection" message to the portal.

In fixing this, I also realised that I think this has (positive) audit consequences. In particular, this will now correctly report access to a resource if it is overlapping as described above (i.e. a narrower overlapping resource is added whilst being connected to one with a wider range). I believe that previously, this access would have not been reported because we would have simply routed the packet to the already connected gateway.

Fixes: #5054.

Copy link

vercel bot commented May 22, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

1 Ignored Deployment
Name Status Preview Comments Updated (UTC)
firezone ⬜️ Ignored (Inspect) Visit Preview May 24, 2024 5:46am

@thomaseizinger thomaseizinger marked this pull request as draft May 22, 2024 05:56
@github-actions github-actions bot added the kind/bug Something isn't working label May 22, 2024
@thomaseizinger
Copy link
Member Author

Draft because it is stacked, otherwise ready for review.

@jamilbk Please review the PR description to make sure the new behaviour is what we want.

Copy link

github-actions bot commented May 22, 2024

Terraform Cloud Plan Output

Plan: 15 to add, 15 to change, 15 to destroy.

Terraform Cloud Plan

Copy link

github-actions bot commented May 22, 2024

Performance Test Results

TCP

Test Name Received/s Sent/s Retransmits
direct-tcp-client2server 238.5 MiB (-1%) 240.7 MiB (-1%) 194 (-57%)
direct-tcp-server2client 239.3 MiB (-1%) 240.2 MiB (-1%) 521 (+62%)
relayed-tcp-client2server 221.7 MiB (-2%) 222.9 MiB (-2%) 233 (-3%)
relayed-tcp-server2client 235.5 MiB (-2%) 236.1 MiB (-2%) 407 (+7%)

UDP

Test Name Total/s Jitter Lost
direct-udp-client2server 500.0 MiB (+0%) 0.03ms (-22%) 43.33% (-4%)
direct-udp-server2client 500.0 MiB (-0%) 0.01ms (-49%) 22.72% (+7%)
relayed-udp-client2server 500.0 MiB (+0%) 0.04ms (-66%) 55.62% (+2%)
relayed-udp-server2client 500.0 MiB (+0%) 0.06ms (+268%) 46.14% (-3%)

Base automatically changed from chore/connlib/tests-send-transmit to main May 22, 2024 23:23
@thomaseizinger thomaseizinger force-pushed the fix/connlib/pick-gateway-based-on-resource-ip branch from 09bd673 to 65d52a1 Compare May 22, 2024 23:28
@thomaseizinger thomaseizinger marked this pull request as ready for review May 22, 2024 23:29
Copy link
Member

@jamilbk jamilbk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't speak to the Rust stuff but yes the behavior is what we want.

Copy link
Collaborator

@conectado conectado left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems pretty good but maybe some additional benchmarks are in order? Our benchmarks right now have very few resources

Comment on lines 833 to 836
let maybe_dns_resource_id = self
.dns_resources_internal_ips
.iter()
.find_map(|(r, i)| i.contains(&destination).then_some(r.id));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this cause a performance regression? Might be worth the extra state keeping an additional table mapping ip addrs to peers?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I thought about that too. I think using an IpNetworkTable would make sense here. More ergonomic to use as well.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need that, since we always assign IpAddrs for dns resources or you want to combine both CIDR and DNS on a single table?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, you mean a regular HashMap. Yeah that makes more sense. We'd always to an exact_match so it is redundant to use an IpNetworkTable.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, it could be combined though! Like into a more general "routing table":

  • CIDR resources go straight into that routing table
  • Resolved DNS IPs also go into that table

Each packet goes through the path of:

  • Lookup destination IP in routing table to find our ResourceId
  • Lookup gateway based on resource ID
  • Connect to gateway if aren't yet connected

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've captured this idea in #5114.

@thomaseizinger
Copy link
Member Author

@conectado I've swapped the map to go from IP to DnsResource instead. Let me know what you think.

Copy link
Collaborator

@conectado conectado left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah with this I don't think there will be any performance change, nice!

@thomaseizinger thomaseizinger added this pull request to the merge queue May 25, 2024
Merged via the queue into main with commit 97ae522 May 25, 2024
135 checks passed
@thomaseizinger thomaseizinger deleted the fix/connlib/pick-gateway-based-on-resource-ip branch May 25, 2024 02:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/bug Something isn't working
Projects
None yet
Development

Successfully merging this pull request may close these issues.

connlib: packets are routed based on connected gateways and not resources
3 participants