Singbox on disable, checks if wireguard is active, and kills it
This commit is contained in:
parent
732b17fb4a
commit
5dc1463862
8 changed files with 102 additions and 18 deletions
|
|
@ -1,23 +1,24 @@
|
||||||
from core.services.profiles.ProfileRepository import ProfileRepository
|
from core.services.profiles.ProfileRepository import ProfileRepository
|
||||||
from core.services.networking.systemwide.systemwide_wireguard import terminate_system_connection
|
# from core.services.networking.systemwide.systemwide_wireguard import terminate_system_connection
|
||||||
from core.services.networking.general_connection_tools.testing_evaluating import system_uses_wireguard_interface
|
# from core.services.networking.general_connection_tools.testing_evaluating import system_uses_wireguard_interface
|
||||||
from core.services.networking.general_connection_tools.connection_enable import establish_connection
|
# from core.services.networking.general_connection_tools.connection_enable import establish_connection
|
||||||
from core.services.networking.systemwide.systemwide_utils import get_firewall_setting, get_dns_setting
|
# from core.services.networking.systemwide.systemwide_utils import get_firewall_setting, get_dns_setting
|
||||||
from core.services.networking.systemwide.encrypted_proxy.singbox_runner import end_singbox
|
# from core.services.networking.systemwide.encrypted_proxy.singbox_runner import end_singbox
|
||||||
from core.services.networking.systemwide import killswitch
|
# from core.services.networking.systemwide import killswitch
|
||||||
from core.services.subscriptions import subscriptions
|
from core.services.subscriptions import subscriptions
|
||||||
from core.errors.exceptions import FirewallError
|
# from core.errors.exceptions import FirewallError
|
||||||
from core.models.Result import Result, ResultError
|
from core.models.Result import Result, ResultError
|
||||||
from core.observers.TicketObserver import TicketObserver
|
# from core.observers.TicketObserver import TicketObserver
|
||||||
# from core.services.assassin.ticket_respawn import respawn_profile
|
# from core.services.assassin.ticket_respawn import respawn_profile
|
||||||
# from core.services.assassin import assassin_tools
|
# from core.services.assassin import assassin_tools
|
||||||
from core.errors.logger import logger
|
from core.errors.logger import logger
|
||||||
|
|
||||||
from core.Errors import InvalidSubscriptionError, MissingSubscriptionError, ConnectionTerminationError, ProfileActivationError, ProfileDeactivationError, MissingLocationError, ConnectionUnprotectedError, EndpointVerificationError, ProfileStateConflictError
|
from core.Errors import InvalidSubscriptionError, MissingSubscriptionError
|
||||||
from core.controllers.ApplicationController import ApplicationController
|
#, ConnectionTerminationError, ProfileActivationError, ProfileDeactivationError, MissingLocationError, ConnectionUnprotectedError, EndpointVerificationError, ProfileStateConflictError
|
||||||
from core.controllers.ApplicationVersionController import ApplicationVersionController
|
# from core.controllers.ApplicationController import ApplicationController
|
||||||
from core.controllers.SessionStateController import SessionStateController
|
# from core.controllers.ApplicationVersionController import ApplicationVersionController
|
||||||
from core.controllers.SystemStateController import SystemStateController
|
# from core.controllers.SessionStateController import SessionStateController
|
||||||
|
# from core.controllers.SystemStateController import SystemStateController
|
||||||
from core.models.BaseProfile import BaseProfile as Profile
|
from core.models.BaseProfile import BaseProfile as Profile
|
||||||
from core.models.Subscription import Subscription
|
from core.models.Subscription import Subscription
|
||||||
from core.models.session.SessionProfile import SessionProfile
|
from core.models.session.SessionProfile import SessionProfile
|
||||||
|
|
|
||||||
15
core/controllers/profile_state/get_profile_data.py
Normal file
15
core/controllers/profile_state/get_profile_data.py
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
from core.models.enum_models import ProtocolChoice, valid_enum
|
||||||
|
from core.controllers.ProfileController import ProfileController
|
||||||
|
|
||||||
|
|
||||||
|
def get_protocol_enum(profile_id: int) -> ProtocolChoice|bool:
|
||||||
|
"""Return the Enum for a given Profile's Protocol Choice"""
|
||||||
|
|
||||||
|
profile = ProfileController.get(profile_id)
|
||||||
|
|
||||||
|
protocol_string = profile.connection.code
|
||||||
|
|
||||||
|
if not valid_enum(protocol_string, ProtocolChoice):
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return ProtocolChoice(protocol_string)
|
||||||
|
|
@ -8,6 +8,8 @@ class ProtocolChoice(Enum):
|
||||||
SOCK5_PROXY = "proxy"
|
SOCK5_PROXY = "proxy"
|
||||||
# MASKED_WIREGUARD = "masked_wireguard"
|
# MASKED_WIREGUARD = "masked_wireguard"
|
||||||
|
|
||||||
|
SINGBOX_PROTOCOLS = [ProtocolChoice.HYSTERIA2, ProtocolChoice.VLESS]
|
||||||
|
|
||||||
class Currency(Enum):
|
class Currency(Enum):
|
||||||
MONERO = "monero"
|
MONERO = "monero"
|
||||||
BITCOIN = "bitcoin"
|
BITCOIN = "bitcoin"
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
|
from core.models.enum_models import ProtocolChoice
|
||||||
from core.Constants import Constants
|
from core.Constants import Constants
|
||||||
|
|
||||||
|
# generic
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from dataclasses_json import dataclass_json
|
from dataclasses_json import dataclass_json
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
@ -14,6 +17,7 @@ class SystemState:
|
||||||
profile_id: int
|
profile_id: int
|
||||||
firewalled: bool
|
firewalled: bool
|
||||||
dns_set: bool
|
dns_set: bool
|
||||||
|
protocol: ProtocolChoice
|
||||||
process_id: Optional[int] = None
|
process_id: Optional[int] = None
|
||||||
|
|
||||||
def save(self: Self):
|
def save(self: Self):
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,7 @@ def launch_encrypted_proxy(
|
||||||
tries = tries + 1
|
tries = tries + 1
|
||||||
|
|
||||||
if exists_already:
|
if exists_already:
|
||||||
|
logger.info("The config exists already, attempting to get the IP from it...")
|
||||||
server_ip = get_value_from_json_file(filepath=config_path, category="outbounds", key="server")
|
server_ip = get_value_from_json_file(filepath=config_path, category="outbounds", key="server")
|
||||||
else:
|
else:
|
||||||
server_ip = setup_config_and_return_ip(
|
server_ip = setup_config_and_return_ip(
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
from core.models.enum_models import ProtocolChoice, SINGBOX_PROTOCOLS
|
||||||
|
from core.models.system.SystemState import SystemState
|
||||||
|
from core.utils.type_checker import type_checker
|
||||||
|
from core.models.Result import Result
|
||||||
|
from core.errors.logger import logger
|
||||||
|
|
||||||
|
@type_checker
|
||||||
|
def kill_any_protocol(current_state: SystemState, active_protocol: ProtocolChoice) -> Result:
|
||||||
|
"""Kill any protocol that's currently active"""
|
||||||
|
|
||||||
|
logger.info(f"Killing the external protocol {active_protocol}")
|
||||||
|
|
||||||
|
firewall = current_state.firewalled
|
||||||
|
dns_set = current_state.dns_set
|
||||||
|
|
||||||
|
if active_protocol == ProtocolChoice.WIREGUARD:
|
||||||
|
from core.services.networking.systemwide_wireguard import terminate_system_connection
|
||||||
|
terminate_system_connection(
|
||||||
|
firewall_setting=firewall,
|
||||||
|
dns_setting=dns_set
|
||||||
|
)
|
||||||
|
return Result(valid=True)
|
||||||
|
|
||||||
|
elif active_protocol in SINGBOX_PROTOCOLS:
|
||||||
|
from core.services.networking.systemwide.encrypted_proxy.singbox_runner import end_singbox
|
||||||
|
return end_singbox()
|
||||||
|
|
||||||
|
else:
|
||||||
|
logger.error("Not a supported Systemwide Profile.")
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
from core.controllers.profile_state.get_profile_data import get_protocol_enum
|
||||||
|
from core.models.enum_models import ProtocolChoice
|
||||||
|
from core.services.networking.general_connection_tools.cross_protocol import kill_any_protocol
|
||||||
from core.services.networking.systemwide.encrypted_proxy import singbox
|
from core.services.networking.systemwide.encrypted_proxy import singbox
|
||||||
from core.services.networking.systemwide.encrypted_proxy.close_singbox import orchestrate_closing
|
from core.services.networking.systemwide.encrypted_proxy.close_singbox import orchestrate_closing
|
||||||
from core.services.networking.systemwide.general_tools import interface_tools
|
from core.services.networking.systemwide.general_tools import interface_tools
|
||||||
|
|
@ -137,6 +140,9 @@ def end_singbox() -> Result:
|
||||||
# get by systemstate:
|
# get by systemstate:
|
||||||
current_state = SystemState.get()
|
current_state = SystemState.get()
|
||||||
|
|
||||||
|
# ------------------
|
||||||
|
# KILL ZOMBIE SINGBOX NOT TIED TO PROFILES
|
||||||
|
# ------------------
|
||||||
if not current_state:
|
if not current_state:
|
||||||
# Make sure there's no singbox id:
|
# Make sure there's no singbox id:
|
||||||
singbox_pid = pid_tools.get_pid_by_app_name(exact_app_name="sing-box")
|
singbox_pid = pid_tools.get_pid_by_app_name(exact_app_name="sing-box")
|
||||||
|
|
@ -154,7 +160,18 @@ def end_singbox() -> Result:
|
||||||
|
|
||||||
logger.error(f"Critical Issue! State JSON is blank, but Singbox is still running. {singbox_pid}")
|
logger.error(f"Critical Issue! State JSON is blank, but Singbox is still running. {singbox_pid}")
|
||||||
|
|
||||||
# kill the real singbox
|
|
||||||
|
# ------------------
|
||||||
|
# KILL NON-SINGBOX SUCH AS WIREGUARD
|
||||||
|
# ------------------
|
||||||
|
active_protocol = get_protocol_enum(current_state.profile_id)
|
||||||
|
logger.info(f"State JSON shows there is already an active profile with id {profile_id} and protocol {active_protocol}")
|
||||||
|
if active_protocol not in SINGBOX_PROTOCOLS:
|
||||||
|
return kill_external_protocol(current_state=current_state, active_protocol=active_protocol)
|
||||||
|
|
||||||
|
# ------------------
|
||||||
|
# KILL THE "REAL" KNOWN ACTIVE SINGBOX PROFILE
|
||||||
|
# ------------------
|
||||||
try:
|
try:
|
||||||
killed_existing = orchestrate_closing(
|
killed_existing = orchestrate_closing(
|
||||||
current_state=current_state,
|
current_state=current_state,
|
||||||
|
|
@ -250,6 +267,7 @@ def start_singbox(
|
||||||
# ============= CHECK INTERFACE =============
|
# ============= CHECK INTERFACE =============
|
||||||
if connection_observer:
|
if connection_observer:
|
||||||
connection_observer.notify("connecting", "Testing Interface..")
|
connection_observer.notify("connecting", "Testing Interface..")
|
||||||
|
print(f"The Constants.SINGBOX_TUN_IF is {Constants.SINGBOX_TUN_IF}")
|
||||||
interface_result = interface_tools.get_output(Constants.SINGBOX_TUN_IF)
|
interface_result = interface_tools.get_output(Constants.SINGBOX_TUN_IF)
|
||||||
if not interface_result.valid:
|
if not interface_result.valid:
|
||||||
error_msg = f"We could not get the interface's output, despite having a process id of {process_id}"
|
error_msg = f"We could not get the interface's output, despite having a process id of {process_id}"
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
from core.models.enum_models import ProtocolChoice, valid_enum
|
||||||
from core.controllers.ConnectionController import ConnectionController
|
from core.controllers.ConnectionController import ConnectionController
|
||||||
from core.controllers.ProfileController import ProfileController
|
from core.controllers.ProfileController import ProfileController
|
||||||
from core.services.networking.systemwide.systemwide_wireguard import terminate_system_connection
|
from core.services.networking.systemwide.systemwide_wireguard import terminate_system_connection
|
||||||
|
|
@ -102,7 +103,7 @@ def enable_session_profile(
|
||||||
profile_observer.notify('enabled', profile)
|
profile_observer.notify('enabled', profile)
|
||||||
|
|
||||||
ApplicationController.launch(application_version, profile, port_number, asynchronous=asynchronous, profile_observer=profile_observer, ticket_observer=ticket_observer, connection_observer=connection_observer)
|
ApplicationController.launch(application_version, profile, port_number, asynchronous=asynchronous, profile_observer=profile_observer, ticket_observer=ticket_observer, connection_observer=connection_observer)
|
||||||
return Result(valid=True)
|
return Result(valid=True, data=profile.type)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -125,7 +126,7 @@ def enable_profile(
|
||||||
if not ProfileStateConflictError in ignore:
|
if not ProfileStateConflictError in ignore:
|
||||||
raise ProfileStateConflictError('The profile is already enabled or its session was not properly terminated.')
|
raise ProfileStateConflictError('The profile is already enabled or its session was not properly terminated.')
|
||||||
else:
|
else:
|
||||||
ProfileController.disable(profile)
|
disable_profile(profile)
|
||||||
|
|
||||||
# =========== PRISTINE ============
|
# =========== PRISTINE ============
|
||||||
if pristine:
|
if pristine:
|
||||||
|
|
@ -155,7 +156,7 @@ def enable_profile(
|
||||||
if connection_result.valid:
|
if connection_result.valid:
|
||||||
if profile_observer is not None:
|
if profile_observer is not None:
|
||||||
profile_observer.notify('enabled', profile)
|
profile_observer.notify('enabled', profile)
|
||||||
return Result(valid=True)
|
return Result(valid=True, data=profile.type)
|
||||||
else:
|
else:
|
||||||
logger.error(f"Couldn't enable the profile: {connection_result.error_type}")
|
logger.error(f"Couldn't enable the profile: {connection_result.error_type}")
|
||||||
error_msg = connection_result.message
|
error_msg = connection_result.message
|
||||||
|
|
@ -312,3 +313,16 @@ def destroy_profile(
|
||||||
profile_observer.notify('destroyed', profile)
|
profile_observer.notify('destroyed', profile)
|
||||||
|
|
||||||
return Result(valid=True, message="Deleted Profile")
|
return Result(valid=True, message="Deleted Profile")
|
||||||
|
|
||||||
|
|
||||||
|
def get_protocol_enum(profile_id: int) -> ProtocolChoice|bool:
|
||||||
|
"""Return the Enum for a given Profile's Protocol Choice"""
|
||||||
|
|
||||||
|
profile = ProfileController.get(profile_id)
|
||||||
|
|
||||||
|
protocol_string = profile.connection.code
|
||||||
|
|
||||||
|
if not valid_enum(protocol_string, ProtocolChoice):
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return ProtocolChoice(protocol_string)
|
||||||
Loading…
Reference in a new issue