mirror of
https://github.com/outbackdingo/firezone.git
synced 2026-01-27 10:18:54 +00:00
connlib: add client dns interception support (#1807)
This commit is contained in:
@@ -118,7 +118,7 @@ services:
|
||||
client:
|
||||
environment:
|
||||
FZ_URL: "ws://api:8081/"
|
||||
FZ_SECRET: "SFMyNTY.g2gDaANkAAhpZGVudGl0eW0AAAAkN2RhN2QxY2QtMTExYy00NGE3LWI1YWMtNDAyN2I5ZDIzMGU1bQAAACAZ_F7tY7RZcWcaeGbwM9H9EBDdj2U4QPu2sBzD8Z_7R24GAMH8mfqIAWIB4TOA.2IZ089fjvNLoCsirq2PwNTfMHXf3285F6YcNquk6niU"
|
||||
FZ_SECRET: "SFMyNTY.g2gDaAN3CGlkZW50aXR5bQAAACQ3ZGE3ZDFjZC0xMTFjLTQ0YTctYjVhYy00MDI3YjlkMjMwZTVtAAAAIBn8Xu1jtFlxZxp4ZvAz0f0QEN2PZThA-7awHMPxn_tHbgYAbLRvQokBYgHhM38.pM-prhb7uvvCVKf51-tAUMEtMzLPZk1n3nLsY44dGFA"
|
||||
RUST_LOG: headless=trace,firezone_client_connlib=trace,firezone_tunnel=trace,libs_common=trace,warn
|
||||
build:
|
||||
context: rust
|
||||
@@ -126,6 +126,9 @@ services:
|
||||
args:
|
||||
PACKAGE: headless
|
||||
image: firezone-headless
|
||||
dns:
|
||||
- 100.100.111.1
|
||||
- 8.8.8.8
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
sysctls:
|
||||
@@ -142,7 +145,7 @@ services:
|
||||
gateway:
|
||||
environment:
|
||||
FZ_URL: "ws://api:8081/"
|
||||
FZ_SECRET: "SFMyNTY.g2gDaAJtAAAAJDNjZWYwNTY2LWFkZmQtNDhmZS1hMGYxLTU4MDY3OTYwOGY2Zm0AAABAamp0enhSRkpQWkdCYy1vQ1o5RHkyRndqd2FIWE1BVWRwenVScjJzUnJvcHg3NS16bmhfeHBfNWJUNU9uby1yYm4GAFvAb_mIAWIAAVGA.1DaY3H3fKzW5sqcciJqlHyG0uFctzOewofsVRGS7NrQ"
|
||||
FZ_SECRET: "SFMyNTY.g2gDaAJtAAAAJDNjZWYwNTY2LWFkZmQtNDhmZS1hMGYxLTU4MDY3OTYwOGY2Zm0AAABAamp0enhSRkpQWkdCYy1vQ1o5RHkyRndqd2FIWE1BVWRwenVScjJzUnJvcHg3NS16bmhfeHBfNWJUNU9uby1yYm4GAEC0b0KJAWIAAVGA.9Oirn9t8rvQpfOhW7hwGBFVzeMm9di0xYGTlwf9cFFk"
|
||||
RUST_LOG: gateway=trace,firezone_gateway_connlib=trace,firezone_tunnel=trace,libs_common=trace,warn
|
||||
ENABLE_MASQUERADE: 1
|
||||
build:
|
||||
@@ -178,7 +181,7 @@ services:
|
||||
PUBLIC_IP4_ADDR: 172.28.0.101
|
||||
LISTEN_IP4_ADDR: 172.28.0.101
|
||||
PORTAL_WS_URL: "ws://api:8081/"
|
||||
PORTAL_TOKEN: "SFMyNTY.g2gDaAJtAAAAJDcyODZiNTNkLTA3M2UtNGM0MS05ZmYxLWNjODQ1MWRhZDI5OW0AAABARVg3N0dhMEhLSlVWTGdjcE1yTjZIYXRkR25mdkFEWVFyUmpVV1d5VHFxdDdCYVVkRVUzbzktRmJCbFJkSU5JS24GAJZ5vfiIAWIAAVGA.F1J6PxmFwmlSYtsUnkw2Z7IjpMkB1oS7wxtzQBqlFFM"
|
||||
PORTAL_TOKEN: "SFMyNTY.g2gDaAJtAAAAJDcyODZiNTNkLTA3M2UtNGM0MS05ZmYxLWNjODQ1MWRhZDI5OW0AAABARVg3N0dhMEhLSlVWTGdjcE1yTjZIYXRkR25mdkFEWVFyUmpVV1d5VHFxdDdCYVVkRVUzbzktRmJCbFJkSU5JS24GAFSzb0KJAWIAAVGA.waeGE26tbgkgIcMrWyck0ysv9SHIoHr0zqoM3wao84M"
|
||||
RUST_LOG: "debug"
|
||||
RUST_BACKTRACE: 1
|
||||
build:
|
||||
|
||||
@@ -208,7 +208,7 @@ IO.puts("")
|
||||
Resources.create_resource(
|
||||
%{
|
||||
type: :dns,
|
||||
address: "gitlab.mycorp.com",
|
||||
address: "google.com",
|
||||
connections: [%{gateway_group_id: gateway_group.id}]
|
||||
},
|
||||
admin_subject
|
||||
|
||||
67
rust/Cargo.lock
generated
67
rust/Cargo.lock
generated
@@ -986,6 +986,17 @@ dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "domain"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04c9fdb317c54875188fea3e4ae483d4b3cf71b131888e9b7665fd6b020fb327"
|
||||
dependencies = [
|
||||
"octseq",
|
||||
"rand",
|
||||
"time 0.3.22",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ecdsa"
|
||||
version = "0.14.8"
|
||||
@@ -1124,6 +1135,7 @@ dependencies = [
|
||||
"boringtun",
|
||||
"bytes",
|
||||
"chrono",
|
||||
"domain",
|
||||
"futures",
|
||||
"futures-util",
|
||||
"ip_network",
|
||||
@@ -1135,6 +1147,7 @@ dependencies = [
|
||||
"netlink-packet-core",
|
||||
"netlink-packet-route",
|
||||
"parking_lot",
|
||||
"pnet_packet",
|
||||
"rand_core 0.6.4",
|
||||
"rtnetlink",
|
||||
"serde",
|
||||
@@ -1874,6 +1887,12 @@ dependencies = [
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "no-std-net"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65"
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.3"
|
||||
@@ -1944,6 +1963,12 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "octseq"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5190e3482f38446ee3f3ab50b049a16b072b6111cba008381b816598478ba65d"
|
||||
|
||||
[[package]]
|
||||
name = "oid-registry"
|
||||
version = "0.4.0"
|
||||
@@ -2115,6 +2140,48 @@ version = "3.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3d7ddaed09e0eb771a79ab0fd64609ba0afb0a8366421957936ad14cbd13630"
|
||||
|
||||
[[package]]
|
||||
name = "pnet_base"
|
||||
version = "0.33.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "872e46346144ebf35219ccaa64b1dffacd9c6f188cd7d012bd6977a2a838f42e"
|
||||
dependencies = [
|
||||
"no-std-net",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pnet_macros"
|
||||
version = "0.33.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a780e80005c2e463ec25a6e9f928630049a10b43945fea83207207d4a7606f4"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pnet_macros_support"
|
||||
version = "0.33.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6d932134f32efd7834eb8b16d42418dac87086347d1bc7d142370ef078582bc"
|
||||
dependencies = [
|
||||
"pnet_base",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pnet_packet"
|
||||
version = "0.33.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8bde678bbd85cb1c2d99dc9fc596e57f03aa725f84f3168b0eaf33eeccb41706"
|
||||
dependencies = [
|
||||
"glob",
|
||||
"pnet_base",
|
||||
"pnet_macros",
|
||||
"pnet_macros_support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "poly1305"
|
||||
version = "0.8.0"
|
||||
|
||||
@@ -19,7 +19,7 @@ ENV RUST_BACKTRACE=1
|
||||
ENV PATH "/app:$PATH"
|
||||
ENV PACKAGE_NAME ${PACKAGE}
|
||||
RUN apt-get update -y \
|
||||
&& apt-get install -y iputils-ping iptables lsof \
|
||||
&& apt-get install -y iputils-ping iptables lsof iproute2 \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
# Some black magics here:
|
||||
|
||||
@@ -90,6 +90,19 @@ impl ResourceDescription {
|
||||
ResourceDescription::Cidr(r) => vec![r.address],
|
||||
}
|
||||
}
|
||||
pub fn ipv4(&self) -> Option<Ipv4Addr> {
|
||||
match self {
|
||||
ResourceDescription::Dns(r) => Some(r.ipv4),
|
||||
ResourceDescription::Cidr(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ipv6(&self) -> Option<Ipv6Addr> {
|
||||
match self {
|
||||
ResourceDescription::Dns(r) => Some(r.ipv6),
|
||||
ResourceDescription::Cidr(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn id(&self) -> Id {
|
||||
match self {
|
||||
|
||||
@@ -20,8 +20,10 @@ libs-common = { path = "../common" }
|
||||
libc = { version = "0.2", default-features = false, features = ["std", "const-extern-fn", "extra_traits"] }
|
||||
ip_network = { version = "0.4", default-features = false }
|
||||
ip_network_table = { version = "0.2", default-features = false }
|
||||
domain = "0.8"
|
||||
boringtun = { workspace = true }
|
||||
chrono = { workspace = true }
|
||||
pnet_packet = { version = "0.33" }
|
||||
|
||||
# TODO: research replacing for https://github.com/algesten/str0m
|
||||
webrtc = { version = "0.8" }
|
||||
|
||||
120
rust/connlib/libs/tunnel/src/dns.rs
Normal file
120
rust/connlib/libs/tunnel/src/dns.rs
Normal file
@@ -0,0 +1,120 @@
|
||||
use std::{net::IpAddr, sync::Arc};
|
||||
|
||||
use crate::{
|
||||
ip_packet::{to_dns, IpPacket, MutableIpPacket},
|
||||
ControlSignal, Tunnel,
|
||||
};
|
||||
use domain::base::{
|
||||
iana::{Class, Rcode, Rtype},
|
||||
Message, MessageBuilder, ToDname,
|
||||
};
|
||||
use libs_common::{messages::ResourceDescription, Callbacks, DNS_SENTINEL};
|
||||
use pnet_packet::{udp::MutableUdpPacket, MutablePacket, Packet as UdpPacket, PacketSize};
|
||||
|
||||
const DNS_TTL: u32 = 300;
|
||||
const UDP_HEADER_SIZE: usize = 8;
|
||||
|
||||
// We don't need to support multiple questions/qname in a single query because
|
||||
// nobody does it and since this run with each packet we want to squeeze as much optimization
|
||||
// as we can therefore we won't do it.
|
||||
//
|
||||
// See: https://stackoverflow.com/a/55093896
|
||||
impl<C, CB> Tunnel<C, CB>
|
||||
where
|
||||
C: ControlSignal + Send + Sync + 'static,
|
||||
CB: Callbacks + 'static,
|
||||
{
|
||||
fn build_response(
|
||||
self: &Arc<Self>,
|
||||
original_buf: &[u8],
|
||||
mut dns_answer: Vec<u8>,
|
||||
) -> Option<Vec<u8>> {
|
||||
let response_len = dns_answer.len();
|
||||
let original_pkt = IpPacket::new(original_buf)?;
|
||||
let original_dgm = original_pkt.as_udp()?;
|
||||
let hdr_len = original_pkt.packet_size() - original_dgm.payload().len();
|
||||
let mut res_buf = Vec::with_capacity(hdr_len + response_len);
|
||||
|
||||
res_buf.extend_from_slice(&original_buf[..hdr_len]);
|
||||
res_buf.append(&mut dns_answer);
|
||||
|
||||
let mut pkt = MutableIpPacket::new(&mut res_buf)?;
|
||||
let dgm_len = UDP_HEADER_SIZE + response_len;
|
||||
pkt.set_len(hdr_len + response_len, dgm_len);
|
||||
pkt.swap_src_dst();
|
||||
|
||||
let mut dgm = MutableUdpPacket::new(pkt.payload_mut())?;
|
||||
dgm.set_length(dgm_len as u16);
|
||||
dgm.set_source(original_dgm.get_destination());
|
||||
dgm.set_destination(original_dgm.get_source());
|
||||
|
||||
let mut pkt = MutableIpPacket::new(&mut res_buf)?;
|
||||
let udp_checksum = pkt.to_immutable().udp_checksum(&pkt.as_immutable_udp()?);
|
||||
pkt.as_udp()?.set_checksum(udp_checksum);
|
||||
pkt.set_checksum();
|
||||
Some(res_buf)
|
||||
}
|
||||
|
||||
fn build_dns_with_answer<N>(
|
||||
self: &Arc<Self>,
|
||||
message: &Message<[u8]>,
|
||||
qname: &N,
|
||||
qtype: Rtype,
|
||||
resource: &ResourceDescription,
|
||||
) -> Option<Vec<u8>>
|
||||
where
|
||||
N: ToDname + ?Sized,
|
||||
{
|
||||
let msg_buf = Vec::with_capacity(message.as_slice().len() * 2);
|
||||
let msg_builder = MessageBuilder::from_target(msg_buf).expect(
|
||||
"Developer error: we should be always be able to create a MessageBuilder from a Vec",
|
||||
);
|
||||
let mut answer_builder = msg_builder.start_answer(message, Rcode::NoError).ok()?;
|
||||
match qtype {
|
||||
Rtype::A => answer_builder
|
||||
.push((
|
||||
qname,
|
||||
Class::In,
|
||||
DNS_TTL,
|
||||
domain::rdata::A::from(resource.ipv4()?),
|
||||
))
|
||||
.ok()?,
|
||||
Rtype::Aaaa => answer_builder
|
||||
.push((
|
||||
qname,
|
||||
Class::In,
|
||||
DNS_TTL,
|
||||
domain::rdata::Aaaa::from(resource.ipv6()?),
|
||||
))
|
||||
.ok()?,
|
||||
_ => todo!(),
|
||||
}
|
||||
Some(answer_builder.finish())
|
||||
}
|
||||
|
||||
pub(crate) fn check_for_dns(self: &Arc<Self>, buf: &[u8]) -> Option<Vec<u8>> {
|
||||
let packet = IpPacket::new(buf)?;
|
||||
if packet.destination() != IpAddr::from(DNS_SENTINEL) {
|
||||
return None;
|
||||
}
|
||||
let datagram = packet.as_udp()?;
|
||||
let message = to_dns(&datagram)?;
|
||||
let question = message.first_question()?;
|
||||
if matches!(question.qtype(), Rtype::A | Rtype::Aaaa) && !message.header().qr() {
|
||||
if let Some(resource) = self
|
||||
.resources
|
||||
.read()
|
||||
.get_by_name(&ToDname::to_cow(question.qname()).to_string())
|
||||
{
|
||||
let response = self.build_dns_with_answer(
|
||||
message,
|
||||
question.qname(),
|
||||
question.qtype(),
|
||||
resource,
|
||||
)?;
|
||||
return self.build_response(buf, response);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
217
rust/connlib/libs/tunnel/src/ip_packet.rs
Normal file
217
rust/connlib/libs/tunnel/src/ip_packet.rs
Normal file
@@ -0,0 +1,217 @@
|
||||
use std::net::IpAddr;
|
||||
|
||||
use domain::base::message::Message;
|
||||
use pnet_packet::{
|
||||
ip::{IpNextHeaderProtocol, IpNextHeaderProtocols},
|
||||
ipv4::{checksum, Ipv4Packet, MutableIpv4Packet},
|
||||
ipv6::{Ipv6Packet, MutableIpv6Packet},
|
||||
udp::{ipv4_checksum, ipv6_checksum, MutableUdpPacket, UdpPacket},
|
||||
MutablePacket, Packet, PacketSize,
|
||||
};
|
||||
|
||||
const DNS_PORT: u16 = 53;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub(crate) enum MutableIpPacket<'a> {
|
||||
MutableIpv4Packet(MutableIpv4Packet<'a>),
|
||||
MutableIpv6Packet(MutableIpv6Packet<'a>),
|
||||
}
|
||||
|
||||
// no std::mem:;swap? no problem
|
||||
macro_rules! swap_src_dst {
|
||||
($p:expr) => {
|
||||
let src = $p.get_source();
|
||||
let dst = $p.get_destination();
|
||||
$p.set_source(dst);
|
||||
$p.set_destination(src);
|
||||
};
|
||||
}
|
||||
|
||||
impl<'a> MutableIpPacket<'a> {
|
||||
pub(crate) fn new(data: &mut [u8]) -> Option<MutableIpPacket> {
|
||||
match data[0] >> 4 {
|
||||
4 => MutableIpv4Packet::new(data).map(Into::into),
|
||||
6 => MutableIpv6Packet::new(data).map(Into::into),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn set_checksum(&mut self) {
|
||||
if let Self::MutableIpv4Packet(p) = self {
|
||||
p.set_checksum(checksum(&p.to_immutable()));
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn to_immutable(&self) -> IpPacket {
|
||||
match self {
|
||||
Self::MutableIpv4Packet(p) => p.to_immutable().into(),
|
||||
Self::MutableIpv6Packet(p) => p.to_immutable().into(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn as_udp(&mut self) -> Option<MutableUdpPacket> {
|
||||
self.to_immutable()
|
||||
.is_udp()
|
||||
.then(|| MutableUdpPacket::new(self.payload_mut()))
|
||||
.flatten()
|
||||
}
|
||||
|
||||
pub(crate) fn as_immutable_udp(&self) -> Option<UdpPacket> {
|
||||
self.to_immutable()
|
||||
.is_udp()
|
||||
.then(|| UdpPacket::new(self.payload()))
|
||||
.flatten()
|
||||
}
|
||||
|
||||
pub(crate) fn swap_src_dst(&mut self) {
|
||||
match self {
|
||||
Self::MutableIpv4Packet(p) => {
|
||||
swap_src_dst!(p);
|
||||
}
|
||||
Self::MutableIpv6Packet(p) => {
|
||||
swap_src_dst!(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn set_len(&mut self, total_len: usize, payload_len: usize) {
|
||||
match self {
|
||||
Self::MutableIpv4Packet(p) => p.set_total_length(total_len as u16),
|
||||
Self::MutableIpv6Packet(p) => p.set_payload_length(payload_len as u16),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub(crate) enum IpPacket<'a> {
|
||||
Ipv4Packet(Ipv4Packet<'a>),
|
||||
Ipv6Packet(Ipv6Packet<'a>),
|
||||
}
|
||||
|
||||
impl<'a> IpPacket<'a> {
|
||||
pub(crate) fn new(data: &[u8]) -> Option<IpPacket> {
|
||||
match data[0] >> 4 {
|
||||
4 => Ipv4Packet::new(data).map(Into::into),
|
||||
6 => Ipv6Packet::new(data).map(Into::into),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn next_header(&self) -> IpNextHeaderProtocol {
|
||||
match self {
|
||||
Self::Ipv4Packet(p) => p.get_next_level_protocol(),
|
||||
Self::Ipv6Packet(p) => p.get_next_header(),
|
||||
}
|
||||
}
|
||||
|
||||
fn is_udp(&self) -> bool {
|
||||
self.next_header() == IpNextHeaderProtocols::Udp
|
||||
}
|
||||
|
||||
pub(crate) fn as_udp(&self) -> Option<UdpPacket> {
|
||||
self.is_udp()
|
||||
.then(|| UdpPacket::new(self.payload()))
|
||||
.flatten()
|
||||
}
|
||||
|
||||
pub(crate) fn destination(&self) -> IpAddr {
|
||||
match self {
|
||||
Self::Ipv4Packet(p) => p.get_destination().into(),
|
||||
Self::Ipv6Packet(p) => p.get_destination().into(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn udp_checksum(&self, dgm: &UdpPacket<'_>) -> u16 {
|
||||
match self {
|
||||
Self::Ipv4Packet(p) => ipv4_checksum(dgm, &p.get_source(), &p.get_destination()),
|
||||
Self::Ipv6Packet(p) => ipv6_checksum(dgm, &p.get_source(), &p.get_destination()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn to_dns<'a>(pkt: &'a UdpPacket<'a>) -> Option<&'a Message<[u8]>> {
|
||||
(pkt.get_destination() == DNS_PORT)
|
||||
.then(|| Message::from_slice(pkt.payload()).ok())
|
||||
.flatten()
|
||||
}
|
||||
|
||||
impl<'a> Packet for IpPacket<'a> {
|
||||
fn packet(&self) -> &[u8] {
|
||||
match self {
|
||||
Self::Ipv4Packet(p) => p.packet(),
|
||||
Self::Ipv6Packet(p) => p.packet(),
|
||||
}
|
||||
}
|
||||
|
||||
fn payload(&self) -> &[u8] {
|
||||
match self {
|
||||
Self::Ipv4Packet(p) => p.payload(),
|
||||
Self::Ipv6Packet(p) => p.payload(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> PacketSize for IpPacket<'a> {
|
||||
fn packet_size(&self) -> usize {
|
||||
match self {
|
||||
Self::Ipv4Packet(p) => p.packet_size(),
|
||||
Self::Ipv6Packet(p) => p.packet_size(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Packet for MutableIpPacket<'a> {
|
||||
fn packet(&self) -> &[u8] {
|
||||
match self {
|
||||
Self::MutableIpv4Packet(p) => p.packet(),
|
||||
Self::MutableIpv6Packet(p) => p.packet(),
|
||||
}
|
||||
}
|
||||
|
||||
fn payload(&self) -> &[u8] {
|
||||
match self {
|
||||
Self::MutableIpv4Packet(p) => p.payload(),
|
||||
Self::MutableIpv6Packet(p) => p.payload(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> MutablePacket for MutableIpPacket<'a> {
|
||||
fn packet_mut(&mut self) -> &mut [u8] {
|
||||
match self {
|
||||
Self::MutableIpv4Packet(p) => p.packet_mut(),
|
||||
Self::MutableIpv6Packet(p) => p.packet_mut(),
|
||||
}
|
||||
}
|
||||
|
||||
fn payload_mut(&mut self) -> &mut [u8] {
|
||||
match self {
|
||||
Self::MutableIpv4Packet(p) => p.payload_mut(),
|
||||
Self::MutableIpv6Packet(p) => p.payload_mut(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<Ipv4Packet<'a>> for IpPacket<'a> {
|
||||
fn from(pkt: Ipv4Packet<'a>) -> Self {
|
||||
Self::Ipv4Packet(pkt)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<Ipv6Packet<'a>> for IpPacket<'a> {
|
||||
fn from(pkt: Ipv6Packet<'a>) -> Self {
|
||||
Self::Ipv6Packet(pkt)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<MutableIpv4Packet<'a>> for MutableIpPacket<'a> {
|
||||
fn from(pkt: MutableIpv4Packet<'a>) -> Self {
|
||||
Self::MutableIpv4Packet(pkt)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<MutableIpv6Packet<'a>> for MutableIpPacket<'a> {
|
||||
fn from(pkt: MutableIpv6Packet<'a>) -> Self {
|
||||
Self::MutableIpv6Packet(pkt)
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ use boringtun::{
|
||||
};
|
||||
use ip_network::IpNetwork;
|
||||
use ip_network_table::IpNetworkTable;
|
||||
use libs_common::Callbacks;
|
||||
use libs_common::{Callbacks, DNS_SENTINEL};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use bytes::Bytes;
|
||||
@@ -49,7 +49,9 @@ pub use webrtc::peer_connection::sdp::session_description::RTCSessionDescription
|
||||
use index::{check_packet_index, IndexLfsr};
|
||||
|
||||
mod control_protocol;
|
||||
mod dns;
|
||||
mod index;
|
||||
mod ip_packet;
|
||||
mod peer;
|
||||
mod resource_table;
|
||||
|
||||
@@ -241,6 +243,9 @@ where
|
||||
.up()
|
||||
.await
|
||||
.expect("Couldn't initiate interface");
|
||||
iface_config
|
||||
.add_route(&DNS_SENTINEL.into(), self.callbacks())
|
||||
.await?;
|
||||
}
|
||||
|
||||
self.start_timers();
|
||||
@@ -479,6 +484,14 @@ where
|
||||
}
|
||||
};
|
||||
|
||||
tracing::trace!("Reading from iface {res} bytes");
|
||||
|
||||
if let Some(r) = dev.check_for_dns(&src[..res]) {
|
||||
// TODO(ipv4/ipv6)!
|
||||
dev.write4_device_infallible(&r[..]).await;
|
||||
continue;
|
||||
}
|
||||
|
||||
let dst_addr = match Tunn::dst_address(&src[..res]) {
|
||||
Some(addr) => addr,
|
||||
None => continue,
|
||||
|
||||
@@ -52,6 +52,14 @@ impl ResourceTable {
|
||||
self.id_table.get(id)
|
||||
}
|
||||
|
||||
/// Gets the resource by name
|
||||
pub fn get_by_name(&self, name: impl AsRef<str>) -> Option<&ResourceDescription> {
|
||||
// SAFETY: if we found the pointer, due to our internal consistency rules it is in the id_table
|
||||
self.dns_name
|
||||
.get(name.as_ref())
|
||||
.map(|m| unsafe { m.as_ref() })
|
||||
}
|
||||
|
||||
// SAFETY: resource_description must still be in storage since we are going to reference it.
|
||||
unsafe fn remove_resource(&mut self, resource_description: NonNull<ResourceDescription>) {
|
||||
let id = {
|
||||
|
||||
@@ -222,6 +222,7 @@ impl IfaceConfig {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "trace", skip(self, _callbacks))]
|
||||
pub async fn set_iface_config(
|
||||
&mut self,
|
||||
@@ -254,16 +255,6 @@ impl IfaceConfig {
|
||||
.execute()
|
||||
.await?;
|
||||
|
||||
//TODO!
|
||||
/*
|
||||
let name: String = self.name.clone().try_into()?;
|
||||
for dns in &config.dns {
|
||||
//resolvconf::set_dns(&name, dns).await?;
|
||||
}
|
||||
*/
|
||||
|
||||
//nftables::enable_masquerade((config.ipv4_masquerade, config.ipv6_masquerade)).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user