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:
- Each rule is checked in order
- The first rule that matches the destination determines the result
- 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
privatekeyword 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
ExitPolicyRule: Individual rules that make up a policyMicroExitPolicy: Compact port-only policy format
Implementations§
Source§impl ExitPolicy
impl ExitPolicy
Sourcepub fn new(rules: Vec<ExitPolicyRule>) -> Self
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);Sourcepub fn parse(content: &str) -> Result<Self, Error>
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 ruleSourcepub fn from_rules<S: AsRef<str>>(rules: &[S]) -> Result<Self, Error>
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);Sourcepub fn can_exit_to(&self, address: IpAddr, port: u16) -> bool
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 addressport- 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 blockedSourcepub fn can_exit_to_optional(
&self,
address: Option<IpAddr>,
port: Option<u16>,
strict: bool,
) -> bool
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, orNonefor any addressport- The destination port, orNonefor any portstrict- Iftrue, checks if ALL matching destinations are allowed; iffalse, 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));Sourcepub fn is_exiting_allowed(&self) -> bool
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());Sourcepub fn summary(&self) -> String
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");Sourcepub fn has_private(&self) -> bool
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
strip_private: Remove private rulesExitPolicyRule::is_private: Check individual rules
Sourcepub fn strip_private(&self) -> Self
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());Sourcepub fn has_default(&self) -> bool
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
strip_default: Remove default rulesExitPolicyRule::is_default: Check individual rules
Sourcepub fn strip_default(&self) -> Self
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());Sourcepub fn iter(&self) -> impl Iterator<Item = &ExitPolicyRule>
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);
}Sourcepub fn rules(&self) -> &[ExitPolicyRule]
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);Sourcepub fn len(&self) -> usize
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);Sourcepub fn is_empty(&self) -> bool
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
impl Clone for ExitPolicy
Source§fn clone(&self) -> ExitPolicy
fn clone(&self) -> ExitPolicy
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more