use Firewall in game_networking
This commit is contained in:
@@ -1,15 +1,11 @@
|
|||||||
use crate::{gui::settings::BlockMethod, util::system_info::SystemInfo};
|
use crate::{
|
||||||
use std::{error::Error, path::PathBuf};
|
gui::settings::BlockMethod,
|
||||||
use windows::{
|
util::{
|
||||||
Win32::{
|
firewall::{Firewall, RuleDirection, RuleMode, RuleProtocol},
|
||||||
NetworkManagement::WindowsFirewall::{
|
system_info::SystemInfo,
|
||||||
INetFwPolicy2, INetFwRule, NET_FW_ACTION_BLOCK, NET_FW_IP_PROTOCOL_ANY,
|
|
||||||
NET_FW_RULE_DIR_OUT, NetFwPolicy2, NetFwRule,
|
|
||||||
},
|
|
||||||
System::Com::{CLSCTX_INPROC_SERVER, CoCreateInstance},
|
|
||||||
},
|
},
|
||||||
core::BSTR,
|
|
||||||
};
|
};
|
||||||
|
use std::error::Error;
|
||||||
|
|
||||||
const FILTER_NAME_EXE: &str = "[GTA Tools] Block outbound traffic for all of GTA V";
|
const FILTER_NAME_EXE: &str = "[GTA Tools] Block outbound traffic for all of GTA V";
|
||||||
const FILTER_NAME_SAVE_SERVER: &str = "[GTA Tools] Block outbound traffic to Rockstar save server";
|
const FILTER_NAME_SAVE_SERVER: &str = "[GTA Tools] Block outbound traffic to Rockstar save server";
|
||||||
@@ -21,116 +17,79 @@ pub struct GameNetworking {
|
|||||||
|
|
||||||
impl Default for GameNetworking {
|
impl Default for GameNetworking {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
|
let firewall = Firewall::default();
|
||||||
Self {
|
Self {
|
||||||
blocked: if Self::is_save_server_blocked().unwrap() {
|
blocked: if firewall.is_blocked(FILTER_NAME_SAVE_SERVER).unwrap() {
|
||||||
Self::is_save_server_blocked().unwrap()
|
true
|
||||||
} else {
|
} else {
|
||||||
Self::is_exe_blocked().unwrap()
|
firewall.is_blocked(FILTER_NAME_EXE).unwrap()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Mode {
|
|
||||||
EntireGame(PathBuf),
|
|
||||||
SaveServer(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GameNetworking {
|
impl GameNetworking {
|
||||||
fn block_generic(mode: Mode) -> Result<(), Box<dyn Error>> {
|
pub fn block_exe(
|
||||||
let policy: INetFwPolicy2 =
|
&mut self,
|
||||||
unsafe { CoCreateInstance(&NetFwPolicy2, None, CLSCTX_INPROC_SERVER) }?;
|
system_info: &mut SystemInfo,
|
||||||
let rules = unsafe { policy.Rules() }?;
|
firewall: &Firewall,
|
||||||
let filter_name = match mode {
|
) -> Result<(), Box<dyn Error>> {
|
||||||
Mode::EntireGame(_) => FILTER_NAME_EXE,
|
|
||||||
Mode::SaveServer(_) => FILTER_NAME_SAVE_SERVER,
|
|
||||||
};
|
|
||||||
unsafe { rules.Remove(&BSTR::from(filter_name)) }?;
|
|
||||||
let rule: INetFwRule = unsafe { CoCreateInstance(&NetFwRule, None, CLSCTX_INPROC_SERVER) }?;
|
|
||||||
unsafe { rule.SetName(&BSTR::from(filter_name)) }?;
|
|
||||||
match mode {
|
|
||||||
Mode::EntireGame(exe_path) => {
|
|
||||||
let exe_path = BSTR::from(exe_path.to_string_lossy().to_string());
|
|
||||||
unsafe { rule.SetApplicationName(&exe_path) }?;
|
|
||||||
}
|
|
||||||
Mode::SaveServer(save_server_ip) => {
|
|
||||||
unsafe { rule.SetRemoteAddresses(&BSTR::from(save_server_ip)) }?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
unsafe { rule.SetDirection(NET_FW_RULE_DIR_OUT) }?;
|
|
||||||
unsafe { rule.SetEnabled(true.into()) }?;
|
|
||||||
unsafe { rule.SetAction(NET_FW_ACTION_BLOCK) }?;
|
|
||||||
unsafe { rule.SetProtocol(NET_FW_IP_PROTOCOL_ANY.0) }?;
|
|
||||||
unsafe { rules.Add(&rule) }?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn unblock_generic(filter_name: &str) -> Result<(), Box<dyn Error>> {
|
|
||||||
let policy: INetFwPolicy2 =
|
|
||||||
unsafe { CoCreateInstance(&NetFwPolicy2, None, CLSCTX_INPROC_SERVER) }?;
|
|
||||||
let rules = unsafe { policy.Rules() }?;
|
|
||||||
unsafe { rules.Remove(&BSTR::from(filter_name)) }?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_blocked_generic(filter_name: &str) -> Result<bool, Box<dyn Error>> {
|
|
||||||
let policy: INetFwPolicy2 =
|
|
||||||
unsafe { CoCreateInstance(&NetFwPolicy2, None, CLSCTX_INPROC_SERVER) }?;
|
|
||||||
let rules = unsafe { policy.Rules() }?;
|
|
||||||
let rule_exists = unsafe { rules.Item(&BSTR::from(filter_name)) }.is_ok();
|
|
||||||
Ok(rule_exists)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn block_exe(&mut self, system_info: &mut SystemInfo) -> Result<(), Box<dyn Error>> {
|
|
||||||
let Some(exe_path) = system_info.get_game_exe_path() else {
|
let Some(exe_path) = system_info.get_game_exe_path() else {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
Self::block_generic(Mode::EntireGame(exe_path.to_path_buf()))?;
|
firewall.add(
|
||||||
self.blocked = Self::is_exe_blocked()?;
|
FILTER_NAME_EXE,
|
||||||
|
RuleMode::Executable(exe_path.to_path_buf()),
|
||||||
|
RuleDirection::Out,
|
||||||
|
RuleProtocol::Any,
|
||||||
|
)?;
|
||||||
|
self.blocked = firewall.is_blocked(FILTER_NAME_EXE)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unblock_exe(&mut self) -> Result<(), Box<dyn Error>> {
|
pub fn unblock_exe(&mut self, firewall: &Firewall) -> Result<(), Box<dyn Error>> {
|
||||||
Self::unblock_generic(FILTER_NAME_EXE)?;
|
firewall.remove(FILTER_NAME_EXE)?;
|
||||||
self.blocked = Self::is_exe_blocked()?;
|
self.blocked = firewall.is_blocked(FILTER_NAME_EXE)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_exe_blocked() -> Result<bool, Box<dyn Error>> {
|
pub fn block_save_server(
|
||||||
Self::is_blocked_generic(FILTER_NAME_EXE)
|
&mut self,
|
||||||
}
|
save_server_ip: &str,
|
||||||
|
firewall: &Firewall,
|
||||||
pub fn block_save_server(&mut self, save_server_ip: &str) -> Result<(), Box<dyn Error>> {
|
) -> Result<(), Box<dyn Error>> {
|
||||||
Self::block_generic(Mode::SaveServer(save_server_ip.to_owned()))?;
|
firewall.add(
|
||||||
self.blocked = Self::is_save_server_blocked()?;
|
FILTER_NAME_SAVE_SERVER,
|
||||||
|
RuleMode::Address(save_server_ip.to_owned()),
|
||||||
|
RuleDirection::Out,
|
||||||
|
RuleProtocol::Any,
|
||||||
|
)?;
|
||||||
|
self.blocked = firewall.is_blocked(FILTER_NAME_SAVE_SERVER)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unblock_save_server(&mut self) -> Result<(), Box<dyn Error>> {
|
pub fn unblock_save_server(&mut self, firewall: &Firewall) -> Result<(), Box<dyn Error>> {
|
||||||
Self::unblock_generic(FILTER_NAME_SAVE_SERVER)?;
|
firewall.remove(FILTER_NAME_SAVE_SERVER)?;
|
||||||
self.blocked = Self::is_save_server_blocked()?;
|
self.blocked = firewall.is_blocked(FILTER_NAME_SAVE_SERVER)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_save_server_blocked() -> Result<bool, Box<dyn Error>> {
|
|
||||||
Self::is_blocked_generic(FILTER_NAME_SAVE_SERVER)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn ensure_block_exclusivity(
|
pub fn ensure_block_exclusivity(
|
||||||
&mut self,
|
&mut self,
|
||||||
block_method: BlockMethod,
|
block_method: BlockMethod,
|
||||||
|
firewall: &Firewall,
|
||||||
) -> Result<(), Box<dyn Error>> {
|
) -> Result<(), Box<dyn Error>> {
|
||||||
match block_method {
|
match block_method {
|
||||||
BlockMethod::EntireGame => {
|
BlockMethod::EntireGame => {
|
||||||
if Self::is_save_server_blocked()? {
|
if firewall.is_blocked(FILTER_NAME_SAVE_SERVER)? {
|
||||||
self.unblock_save_server()?;
|
self.unblock_save_server(firewall)?;
|
||||||
self.blocked = Self::is_exe_blocked()?;
|
self.blocked = firewall.is_blocked(FILTER_NAME_EXE)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BlockMethod::SaveServer => {
|
BlockMethod::SaveServer => {
|
||||||
if Self::is_exe_blocked()? {
|
if firewall.is_blocked(FILTER_NAME_EXE)? {
|
||||||
self.unblock_exe()?;
|
self.unblock_exe(firewall)?;
|
||||||
self.blocked = Self::is_save_server_blocked()?;
|
self.blocked = firewall.is_blocked(FILTER_NAME_SAVE_SERVER)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-4
@@ -180,13 +180,17 @@ impl App {
|
|||||||
match self.settings.block_method {
|
match self.settings.block_method {
|
||||||
BlockMethod::EntireGame => {
|
BlockMethod::EntireGame => {
|
||||||
self.game_networking
|
self.game_networking
|
||||||
.block_exe(&mut self.system_info)
|
.block_exe(
|
||||||
|
&mut self.system_info,
|
||||||
|
&self.firewall,
|
||||||
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
BlockMethod::SaveServer => {
|
BlockMethod::SaveServer => {
|
||||||
self.game_networking
|
self.game_networking
|
||||||
.block_save_server(
|
.block_save_server(
|
||||||
&self.settings.save_server_ip,
|
&self.settings.save_server_ip,
|
||||||
|
&self.firewall,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
@@ -197,10 +201,14 @@ impl App {
|
|||||||
if ui.button("Unblock").clicked() {
|
if ui.button("Unblock").clicked() {
|
||||||
match self.settings.block_method {
|
match self.settings.block_method {
|
||||||
BlockMethod::EntireGame => {
|
BlockMethod::EntireGame => {
|
||||||
self.game_networking.unblock_exe().unwrap();
|
self.game_networking
|
||||||
|
.unblock_exe(&self.firewall)
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
BlockMethod::SaveServer => {
|
BlockMethod::SaveServer => {
|
||||||
self.game_networking.unblock_save_server().unwrap();
|
self.game_networking
|
||||||
|
.unblock_save_server(&self.firewall)
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -257,7 +265,7 @@ impl App {
|
|||||||
ui.label("Block method");
|
ui.label("Block method");
|
||||||
if let Err(why) = self
|
if let Err(why) = self
|
||||||
.game_networking
|
.game_networking
|
||||||
.ensure_block_exclusivity(self.settings.block_method)
|
.ensure_block_exclusivity(self.settings.block_method, &self.firewall)
|
||||||
{
|
{
|
||||||
log::warn!("Couldn't ensure block exclusivity: {why}");
|
log::warn!("Couldn't ensure block exclusivity: {why}");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ pub enum RuleDirection {
|
|||||||
|
|
||||||
pub enum RuleProtocol {
|
pub enum RuleProtocol {
|
||||||
Any,
|
Any,
|
||||||
|
#[allow(unused)]
|
||||||
Tcp,
|
Tcp,
|
||||||
Udp,
|
Udp,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user