More readme info
This commit is contained in:
parent
00c21c2011
commit
05c39d0fb1
23
README.md
23
README.md
@ -3,9 +3,17 @@
|
|||||||
[](https://docs.rs/protomask)
|
[](https://docs.rs/protomask)
|
||||||
[](https://github.com/Ewpratten/protomask/actions/workflows/build.yml)
|
[](https://github.com/Ewpratten/protomask/actions/workflows/build.yml)
|
||||||
|
|
||||||
**A user space NAT64 implementation.**
|
**A user space [NAT64](https://en.wikipedia.org/wiki/NAT64) implementation.**
|
||||||
|
|
||||||
*Protomask* started as a challenge to create a NAT64 implementation in a weekend. The goal of this implementation is to *keep things simple*. There aren't many knobs to tweak, so if you want to do stateful NAT or source address filtering, put something like `iptables` in front of it.
|
Protomask started as a challenge to create a NAT64 implementation in a weekend. The goal of this implementation is to *keep things simple*. There aren't many knobs to tweak, so if you want to do stateful NAT or source address filtering, put something like `iptables` in front of it.
|
||||||
|
|
||||||
|
## How it works
|
||||||
|
|
||||||
|
Protomask listens on an IPv6 `/96` prefix for incoming traffic.
|
||||||
|
|
||||||
|
When traffic destined for an [embedded IPv4 address](https://datatracker.ietf.org/doc/html/rfc6052) is received, the source IPv6 address is assigned a real IPv4 address from a pool of addresses on a first-come-first-serve basis.
|
||||||
|
|
||||||
|
All further packet from that source IPv6 address will be NAT-ed through its assigned IPv4 address until the reservation expires. The reverse process happens for return traffic too.
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
@ -13,14 +21,15 @@ Protomask uses a [TOML](https://toml.io) configuration file. Here is a functiona
|
|||||||
|
|
||||||
```toml
|
```toml
|
||||||
[Interface]
|
[Interface]
|
||||||
# A list of IPv4 prefixes to map traffic to
|
# The IPv6 prefix to listen for V6 traffic on
|
||||||
Pool = ["44.31.119.0/24"]
|
|
||||||
# The IPv6 prefix to listen for traffic on (should generally be the well-known 64:ff9b::/96 prefix)
|
|
||||||
Prefix = "64:ff9b::/96"
|
Prefix = "64:ff9b::/96"
|
||||||
|
# A list of IPv4 prefixes to map V6 traffic to
|
||||||
|
Pool = ["192.0.2.0/24"]
|
||||||
|
|
||||||
[Rules]
|
[Rules]
|
||||||
# A static mapping of IPv4 and IPv6 addresses
|
# A static mapping of IPv4 and IPv6 addresses
|
||||||
# These addresses will be exclusively reserved, and not used in the general pool
|
# These addresses will not used in the dynamic pool
|
||||||
MapStatic = [{ v4 = "192.0.2.2", v6 = "2001:db8:1::2" }]
|
MapStatic = [{ v4 = "192.0.2.2", v6 = "2001:db8:1::2" }]
|
||||||
|
# How many seconds to keep a dynamic mapping alive for
|
||||||
|
ReservationDuration = 7200 # Optional
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -10,12 +10,6 @@ use ipnet::{Ipv4Net, Ipv6Net};
|
|||||||
/// Interface config
|
/// Interface config
|
||||||
#[derive(Debug, serde::Deserialize)]
|
#[derive(Debug, serde::Deserialize)]
|
||||||
pub struct InterfaceConfig {
|
pub struct InterfaceConfig {
|
||||||
/// IPv4 router address
|
|
||||||
// #[serde(rename = "Address4")]
|
|
||||||
// pub address_v4: Ipv4Addr,
|
|
||||||
// /// IPv6 router address
|
|
||||||
// #[serde(rename = "Address6")]
|
|
||||||
// pub address_v6: Ipv6Addr,
|
|
||||||
/// Ipv4 pool
|
/// Ipv4 pool
|
||||||
#[serde(rename = "Pool")]
|
#[serde(rename = "Pool")]
|
||||||
pub pool: Vec<Ipv4Net>,
|
pub pool: Vec<Ipv4Net>,
|
||||||
@ -34,8 +28,8 @@ pub struct AddressMappingRule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Used to generate the default reservation duration
|
/// Used to generate the default reservation duration
|
||||||
fn default_reservation_duration() -> Duration {
|
fn default_reservation_duration() -> u64 {
|
||||||
Duration::from_secs(7200)
|
7200
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Rules config
|
/// Rules config
|
||||||
@ -46,7 +40,14 @@ pub struct RulesConfig {
|
|||||||
pub static_map: Vec<AddressMappingRule>,
|
pub static_map: Vec<AddressMappingRule>,
|
||||||
/// How long to hold a dynamic mapping for
|
/// How long to hold a dynamic mapping for
|
||||||
#[serde(rename = "ReservationDuration", default="default_reservation_duration")]
|
#[serde(rename = "ReservationDuration", default="default_reservation_duration")]
|
||||||
pub reservation_duration: Duration,
|
reservation_duration: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RulesConfig {
|
||||||
|
/// Get the reservation duration
|
||||||
|
pub fn reservation_duration(&self) -> Duration {
|
||||||
|
Duration::from_secs(self.reservation_duration)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Representation of the `protomask.toml` config file
|
/// Representation of the `protomask.toml` config file
|
||||||
|
@ -60,7 +60,7 @@ pub async fn main() {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|rule| (rule.v6, rule.v4))
|
.map(|rule| (rule.v6, rule.v4))
|
||||||
.collect(),
|
.collect(),
|
||||||
config.rules.reservation_duration,
|
config.rules.reservation_duration(),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user