ExitPolicy

Struct ExitPolicy 

Source
pub struct ExitPolicy { /* private fields */ }
Expand description

A complete exit policy consisting of multiple rules.

An exit policy is an ordered list of ExitPolicyRules that determine whether a Tor relay will allow traffic to exit to a given destination. Rules are evaluated in order, and the first matching rule determines whether traffic is allowed.

§Rule Evaluation

When checking if traffic can exit to a destination:

  1. Each rule is checked in order
  2. The first rule that matches the destination determines the result
  3. If no rule matches, the default is to allow traffic

§Special Rule Sequences

Exit policies may contain special rule sequences that are automatically detected:

  • Private rules: Rules blocking traffic to private/internal IP ranges (expanded from the private keyword in torrc)
  • Default rules: Tor’s standard suffix blocking commonly abused ports

§Example

use stem_rs::exit_policy::ExitPolicy;
use std::net::IpAddr;

// Parse a policy that allows only web traffic
let policy = ExitPolicy::parse("accept *:80, accept *:443, reject *:*").unwrap();

let addr: IpAddr = "192.168.1.1".parse().unwrap();
assert!(policy.can_exit_to(addr, 80));   // HTTP allowed
assert!(policy.can_exit_to(addr, 443));  // HTTPS allowed
assert!(!policy.can_exit_to(addr, 22));  // SSH blocked

// Get a summary
assert_eq!(policy.summary(), "accept 80, 443");

// Check if any exiting is allowed
assert!(policy.is_exiting_allowed());

// A reject-all policy
let reject_all = ExitPolicy::parse("reject *:*").unwrap();
assert!(!reject_all.is_exiting_allowed());

§See Also

Implementations§

Source§

impl ExitPolicy

Source

pub fn new(rules: Vec<ExitPolicyRule>) -> Self

Creates a new exit policy from a vector of rules.

The rules are automatically analyzed to detect private and default rule sequences.

§Arguments
  • rules - The rules that make up this policy
§Example
use stem_rs::exit_policy::{ExitPolicy, ExitPolicyRule};

let rules = vec![
    ExitPolicyRule::parse("accept *:80").unwrap(),
    ExitPolicyRule::parse("reject *:*").unwrap(),
];
let policy = ExitPolicy::new(rules);
assert_eq!(policy.len(), 2);
Source

pub fn parse(content: &str) -> Result<Self, Error>

Parses an exit policy from a string.

The string can contain multiple rules separated by commas or newlines. Rules after a catch-all rule (accept *:* or reject *:*) are ignored.

§Arguments
  • content - The policy string to parse
§Errors

Returns Error::Parse if any rule in the policy is invalid.

§Example
use stem_rs::exit_policy::ExitPolicy;

// Comma-separated rules
let policy = ExitPolicy::parse("accept *:80, accept *:443, reject *:*").unwrap();
assert_eq!(policy.len(), 3);

// Newline-separated rules
let policy = ExitPolicy::parse("accept *:80\naccept *:443\nreject *:*").unwrap();
assert_eq!(policy.len(), 3);

// Rules after catch-all are ignored
let policy = ExitPolicy::parse("reject *:*, accept *:80").unwrap();
assert_eq!(policy.len(), 1);  // Only the reject rule
Source

pub fn from_rules<S: AsRef<str>>(rules: &[S]) -> Result<Self, Error>

Creates an exit policy from a slice of rule strings.

Similar to parse, but takes individual rule strings instead of a single concatenated string.

§Arguments
  • rules - Slice of rule strings
§Errors

Returns Error::Parse if any rule is invalid.

§Example
use stem_rs::exit_policy::ExitPolicy;

let policy = ExitPolicy::from_rules(&[
    "accept *:80",
    "accept *:443",
    "reject *:*",
]).unwrap();
assert_eq!(policy.len(), 3);
Source

pub fn can_exit_to(&self, address: IpAddr, port: u16) -> bool

Checks if traffic can exit to a specific destination.

Evaluates the policy rules in order and returns whether traffic to the given address and port is allowed.

§Arguments
  • address - The destination IP address
  • port - The destination port
§Returns

true if traffic to this destination is allowed, false otherwise.

§Example
use stem_rs::exit_policy::ExitPolicy;
use std::net::IpAddr;

let policy = ExitPolicy::parse("accept *:80, accept *:443, reject *:*").unwrap();
let addr: IpAddr = "192.168.1.1".parse().unwrap();

assert!(policy.can_exit_to(addr, 80));   // HTTP allowed
assert!(policy.can_exit_to(addr, 443));  // HTTPS allowed
assert!(!policy.can_exit_to(addr, 22));  // SSH blocked
Source

pub fn can_exit_to_optional( &self, address: Option<IpAddr>, port: Option<u16>, strict: bool, ) -> bool

Checks if traffic can exit to a destination with optional parameters.

Similar to can_exit_to, but allows omitting the address or port to check if traffic to ANY matching destination is allowed.

§Arguments
  • address - The destination IP address, or None for any address
  • port - The destination port, or None for any port
  • strict - If true, checks if ALL matching destinations are allowed; if false, checks if ANY matching destination is allowed
§Returns

true if traffic is allowed according to the strict mode, false otherwise.

§Example
use stem_rs::exit_policy::ExitPolicy;

let policy = ExitPolicy::parse("reject 10.0.0.0/8:80, accept *:*").unwrap();

// Non-strict: Can ANY address exit on port 80?
assert!(policy.can_exit_to_optional(None, Some(80), false));

// Strict: Can ALL addresses exit on port 80?
assert!(!policy.can_exit_to_optional(None, Some(80), true));
Source

pub fn is_exiting_allowed(&self) -> bool

Checks if this policy allows any exiting at all.

Returns false if the policy effectively blocks all traffic (e.g., reject *:* with no prior accept rules).

§Returns

true if at least some traffic can exit, false if all traffic is blocked.

§Example
use stem_rs::exit_policy::ExitPolicy;

let policy = ExitPolicy::parse("accept *:80, reject *:*").unwrap();
assert!(policy.is_exiting_allowed());

let policy = ExitPolicy::parse("reject *:*").unwrap();
assert!(!policy.is_exiting_allowed());

// Empty policy allows by default
let policy = ExitPolicy::parse("").unwrap();
assert!(policy.is_exiting_allowed());
Source

pub fn summary(&self) -> String

Returns a short summary of the policy, similar to a microdescriptor.

The summary shows which ports are accepted or rejected, ignoring address-specific rules. This is useful for quickly understanding what a relay allows.

§Returns

A string like "accept 80, 443" or "reject 1-1024".

§Example
use stem_rs::exit_policy::ExitPolicy;

let policy = ExitPolicy::parse("accept *:80, accept *:443, reject *:*").unwrap();
assert_eq!(policy.summary(), "accept 80, 443");

let policy = ExitPolicy::parse("accept *:443, reject *:1-1024, accept *:*").unwrap();
assert_eq!(policy.summary(), "reject 1-442, 444-1024");
Source

pub fn has_private(&self) -> bool

Checks if this policy contains rules expanded from the private keyword.

The private keyword in Tor exit policies expands to rules blocking traffic to private/internal IP ranges. This method detects if such rules are present.

§Returns

true if the policy contains private rules, false otherwise.

§See Also
Source

pub fn strip_private(&self) -> Self

Returns a copy of this policy without private rules.

Creates a new policy with all rules expanded from the private keyword removed.

§Returns

A new ExitPolicy without private rules.

§Example
use stem_rs::exit_policy::ExitPolicy;

let policy = ExitPolicy::parse("accept *:80, reject *:*").unwrap();
let stripped = policy.strip_private();
assert!(!stripped.has_private());
Source

pub fn has_default(&self) -> bool

Checks if this policy contains Tor’s default exit policy suffix.

Tor appends a default suffix to exit policies that blocks commonly abused ports (SMTP, NetBIOS, etc.) and then accepts all other traffic.

§Returns

true if the policy ends with the default suffix, false otherwise.

§See Also
Source

pub fn strip_default(&self) -> Self

Returns a copy of this policy without the default suffix.

Creates a new policy with Tor’s default exit policy suffix removed.

§Returns

A new ExitPolicy without default rules.

§Example
use stem_rs::exit_policy::ExitPolicy;

let policy = ExitPolicy::parse("accept *:80, reject *:*").unwrap();
let stripped = policy.strip_default();
assert!(!stripped.has_default());
Source

pub fn iter(&self) -> impl Iterator<Item = &ExitPolicyRule>

Returns an iterator over the rules in this policy.

Rules are yielded in evaluation order (first rule first).

§Example
use stem_rs::exit_policy::ExitPolicy;

let policy = ExitPolicy::parse("accept *:80, reject *:*").unwrap();
for rule in policy.iter() {
    println!("{}", rule);
}
Source

pub fn rules(&self) -> &[ExitPolicyRule]

Returns a slice of all rules in this policy.

§Example
use stem_rs::exit_policy::ExitPolicy;

let policy = ExitPolicy::parse("accept *:80, reject *:*").unwrap();
let rules = policy.rules();
assert_eq!(rules.len(), 2);
Source

pub fn len(&self) -> usize

Returns the number of rules in this policy.

§Example
use stem_rs::exit_policy::ExitPolicy;

let policy = ExitPolicy::parse("accept *:80, reject *:*").unwrap();
assert_eq!(policy.len(), 2);
Source

pub fn is_empty(&self) -> bool

Checks if this policy has no rules.

An empty policy allows all traffic by default.

§Example
use stem_rs::exit_policy::ExitPolicy;

let policy = ExitPolicy::parse("").unwrap();
assert!(policy.is_empty());

let policy = ExitPolicy::parse("accept *:80").unwrap();
assert!(!policy.is_empty());

Trait Implementations§

Source§

impl Clone for ExitPolicy

Source§

fn clone(&self) -> ExitPolicy

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ExitPolicy

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for ExitPolicy

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl FromStr for ExitPolicy

Source§

type Err = Error

The associated error which can be returned from parsing.
Source§

fn from_str(s: &str) -> Result<Self, Self::Err>

Parses a string s to return a value of this type. Read more
Source§

impl PartialEq for ExitPolicy

Source§

fn eq(&self, other: &ExitPolicy) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Eq for ExitPolicy

Source§

impl StructuralPartialEq for ExitPolicy

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.