windows_firewall 0.7.0

A crate for managing Windows Firewall rules and settings.
Documentation
use std::net::IpAddr;
use std::str::FromStr;
use windows_firewall::{
    Action, Direction, InterfaceType::Lan, InterfaceType::RemoteAccess, InterfaceType::Wireless,
    Profile, Protocol,
};
use windows_firewall::{Address, FirewallRule, Port, PortKeyword};

pub fn build_base_rule(name: &str) -> FirewallRule {
    FirewallRule::builder()
        .name(name)
        .action(Action::Allow)
        .direction(Direction::In)
        .enabled(true)
        .build()
}

pub fn build_tcp_full_rule(name: &str) -> FirewallRule {
    FirewallRule::builder()
        .name(name)
        .action(Action::Block)
        .direction(Direction::In)
        .enabled(false)
        .description("Block outbound TCP traffic")
        .application_name("C:\\Program Files\\NewApp\\new_app.exe")
        .service_name("NewService")
        .protocol(Protocol::Tcp)
        .local_ports([443, 8443])
        .remote_ports([80, 8080])
        .local_addresses([IpAddr::from_str("172.16.0.1").unwrap()])
        .remote_addresses([IpAddr::from_str("1.1.1.1").unwrap()])
        .interface_types([Lan])
        .grouping("Group B")
        .profiles(Profile::Public)
        .edge_traversal(true)
        .build()
}

pub fn build_icmp_full_rule(name: &str) -> FirewallRule {
    FirewallRule::builder()
        .name(name)
        .action(Action::Allow)
        .direction(Direction::Out)
        .enabled(true)
        .description("Allow outbound ICMPv4 traffic")
        .application_name("C:\\Program Files\\MyApp\\app.exe")
        .service_name("MyService")
        .protocol(Protocol::Icmpv4)
        .local_addresses([
            IpAddr::from_str("192.168.1.1").unwrap(),
            IpAddr::from_str("192.168.1.2").unwrap(),
        ])
        .remote_addresses([
            IpAddr::from_str("10.0.0.1").unwrap(),
            IpAddr::from_str("10.0.0.2").unwrap(),
        ])
        .icmp_types_and_codes("8:0")
        .interface_types([Wireless, Lan, RemoteAccess])
        .grouping("Group A")
        .profiles(Profile::Private)
        .edge_traversal(false)
        .build()
}

pub fn build_full_rule_for_protocol(name: &str, proto: Protocol) -> FirewallRule {
    let builder = FirewallRule::builder()
        .name(name)
        .action(Action::Allow)
        .direction(Direction::In)
        .enabled(true)
        .description("rule for specific protocol")
        .application_name("C:\\Program Files\\MyApp\\app.exe")
        .service_name("MyService")
        .protocol(proto)
        .local_addresses([
            IpAddr::from_str("192.168.1.1").unwrap(),
            IpAddr::from_str("192.168.1.2").unwrap(),
        ])
        .remote_addresses([
            IpAddr::from_str("10.0.0.1").unwrap(),
            IpAddr::from_str("10.0.0.2").unwrap(),
        ])
        .interface_types([Wireless, Lan])
        .grouping("Group A")
        .profiles(Profile::Private)
        .edge_traversal(false);

    match proto {
        Protocol::Tcp | Protocol::Udp => builder.local_ports([1234]).remote_ports([4321]).build(),
        Protocol::Icmpv4 | Protocol::Icmpv6 => builder.icmp_types_and_codes("8:0").build(),
        _ => builder.build(),
    }
}

pub fn build_rule_for_interface(name: &str, interface_name: &str) -> FirewallRule {
    FirewallRule::builder()
        .name(name)
        .action(Action::Allow)
        .direction(Direction::In)
        .enabled(true)
        .interfaces([interface_name])
        .build()
}

pub fn build_rule_for_port(name: &str, port: &Port) -> FirewallRule {
    let rule_builder = FirewallRule::builder()
        .name(name)
        .action(Action::Allow)
        .direction(Direction::In)
        .enabled(true);

    if let Port::Keyword(k) = port {
        let rule_builder = match k {
            PortKeyword::Teredo => rule_builder.protocol(Protocol::Udp),
            _ => rule_builder.protocol(Protocol::Tcp),
        };
        rule_builder.local_ports([Port::from(*k)]).build()
    } else {
        rule_builder
            .protocol(Protocol::Udp)
            .local_ports([port.clone()])
            .remote_ports([port.clone()])
            .build()
    }
}

pub fn build_rule_for_address(name: &str, address: &Address) -> FirewallRule {
    let rule_builder = FirewallRule::builder()
        .name(name)
        .action(Action::Allow)
        .direction(Direction::In)
        .enabled(true);

    if let Address::Keyword(k) = address {
        rule_builder.remote_addresses([Address::from(*k)]).build()
    } else if let Address::Ip(ip) = address {
        rule_builder
            .local_addresses([Address::from(*ip)])
            .remote_addresses([Address::from(*ip)])
            .build()
    } else if let Address::Cidr(cidr) = address {
        rule_builder
            .local_addresses([Address::from(*cidr)])
            .remote_addresses([Address::from(*cidr)])
            .build()
    } else {
        rule_builder
            .local_addresses([address.clone()])
            .remote_addresses([address.clone()])
            .build()
    }
}