diff --git a/iptable.sh b/iptable.sh index 777e427..3895b55 100755 --- a/iptable.sh +++ b/iptable.sh @@ -1,5 +1,5 @@ #!/bin/sh -# set -e + # Flush the tables. This may cut the system's internet. iptables -F iptables -X @@ -19,25 +19,43 @@ iptables -A OUTPUT -j ACCEPT -o tun+ #iptables -A OUTPUT -j ACCEPT -o tun+ iptables -t mangle -A OUTPUT -m owner --gid-owner openvpn -j MARK --set-mark 11 +iptables -t mangle -A OUTPUT -j MARK --set-mark 12 iptables -t nat -A POSTROUTING -m owner --gid-owner openvpn -o enp1s0 -j MASQUERADE echo ip route ip route flush all ip rule flush ip rule add from all lookup main pref 32766 ip rule add from all lookup default pref 32767 -echo add fwmark -ip rule add fwmark 11 table novpn pref 100 -echo add to novpn table + + +echo "create route table if it does not exist" +if [ $(cat /etc/iproute2/rt_tables | grep novpn | wc -l) -eq 0 ]; then + echo "11 novpn" >> /etc/iproute2/rt_tables +fi +if [ $(cat /etc/iproute2/rt_tables | grep balanced | wc -l) -eq 0 ]; then + echo "10 balanced" >> /etc/iproute2/rt_tables +fi + +echo "add to novpn table" ip route flush table novpn -ip route add 192.168.122.0/24 dev enp1s0 # src 192.168.122.128 -#ip route add 192.168.122.0/24 dev enp1s0 table novpn +ip route add 192.168.122.0/24 dev enp1s0 ip route add default via 192.168.122.1 dev enp1s0 table novpn -echo add to default table + +echo "add to balanced table" +ip route flush table balanced +ip route add default via 192.168.122.1 dev enp1s0 table balanced + +echo "add to default table" # need to add a default route for the routing code to trigger the fwmark rule at all, else there's a direct "Network is unreachable" with no packet generated. -ip route add default via 192.168.122.254 dev enp1s0 # not exist -echo rp_filter +ip route add default via 192.168.122.254 dev enp1s0 + +echo "disable rp_filter" for i in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 0 > $i; done +echo "add ip rule fwmark" +ip rule add fwmark 12 table balanced pref 98 +ip rule add fwmark 11 table novpn pref 99 + # We should permit replies to traffic we've sent out. iptables -A INPUT -j ACCEPT -m state --state ESTABLISHED diff --git a/o_manager.py b/o_manager.py index 5dc53e4..2d57aca 100644 --- a/o_manager.py +++ b/o_manager.py @@ -17,8 +17,8 @@ class OManager: os.makedirs(folder_path) if not name: name = f"openvpn-{self.idx}" - op = Openvpn(cfg_fp, interface, folder_path, - f"{self.base_port + self.idx}", name=name, + op = Openvpn(cfg_fp, self.idx, folder_path, + f"{self.base_port + self.idx}", "script.sh.template", name=name, additional_cfg=additional_cfg) self.ops.append(op) self.idx += 1 diff --git a/openvpn.py b/openvpn.py index d6d51ae..68286c4 100644 --- a/openvpn.py +++ b/openvpn.py @@ -11,6 +11,8 @@ import psutil import subprocess from datetime import datetime import humanize +from tornado.template import Template +import stat def generate_config(in_fp, cfg): @@ -39,9 +41,10 @@ RUNNING = "running" class Openvpn: - def __init__(self, cfg_fp, interface, folder_path, management_port, name=None, additional_cfg={}, loop=None): + def __init__(self, cfg_fp, idx, folder_path, management_port, template_fp, name=None, additional_cfg={}, loop=None): self.cfg_fp = cfg_fp - self.interface = interface + self.idx = idx + self.interface = f"tun{idx}" self.folder_path = folder_path self.management_port = management_port self.PID = 0 @@ -56,12 +59,33 @@ class Openvpn: # TODO: update paths function self.io_stat_fp = os.path.join(self.folder_path, "io_stat.txt") self.ping_stat_fp = os.path.join(self.folder_path, "ping_stat.txt") - + self.template_fp = template_fp if loop: self.loop = loop else: self.loop = asyncio.get_event_loop() + def generate_script(self): + self.script_fp = os.path.join(self.folder_path, "cfg.txt") + + with open(self.template_fp, "r") as template_f: + buf = template_f.read() + template = Template(buf) + script_log_fp = os.path.join(self.folder_path, "script_log.txt") + items = { + "script_log_fp": script_log_fp, + "route_table_name": f"vpn{self.idx}", + "route_table_id": f"{300+self.idx}", + "rule_pref": f"{100+self.idx}" + } + script = template.generate(**items) + with open(self.script_fp, "wb") as script_f: + script_f.write(script) + # mark executable + st = os.stat(self.script_fp) + os.chmod(self.script_fp, st.st_mode | stat.S_IEXEC) + return self.script_fp + def get_cfg(self): self.log_fp = os.path.join(self.folder_path, "log.txt") cfg = { @@ -85,9 +109,9 @@ class Openvpn: if self.status == IDLE: self.status = RUNNING config_fp = self.generate_config_file() - route_up_script = os.path.join(self.folder_path, "test.sh") + script_fp = self.generate_script() cmd = " ".join(["openvpn", "--config", config_fp, "--route-noexec", - "--route-up", route_up_script, "--script-security", + "--route-up", script_fp, "--script-security", "2", "--mute-replay-warnings"]) # TODO: remove --mute-replay-warnings self.run_task.append(self.loop.create_task(self.run(cmd))) self.run_task.append(self.loop.create_task(self.monitor_task())) @@ -233,6 +257,6 @@ class Openvpn: if __name__ == "__main__": folder_fp = "/home/mantao/Desktop/t/" cfg_fp = "/home/mantao/Desktop/t/TCP_Files/UK2-TCP.ovpn" - o1 = Openvpn(cfg_fp, "tun0", folder_fp, 8001, additional_cfg={ + o1 = Openvpn(cfg_fp, 0, folder_fp, 8001, "script.sh.template", additional_cfg={ "auth-user-pass": "/home/mantao/Desktop/t/fast.txt"}) # o1.start() diff --git a/script.sh.template b/script.sh.template new file mode 100644 index 0000000..4cd837a --- /dev/null +++ b/script.sh.template @@ -0,0 +1,21 @@ +#!/bin/sh +echo ============================== >> {{script_log_fp}} +env >> {{script_log_fp}} + +# create route table if it does not exist +if [ $(cat /etc/iproute2/rt_tables | grep {{route_table_name}} | wc -l) -eq 0 ]; then + echo "{{route_table_id}} {{route_table_name}}" >> /etc/iproute2/rt_tables +fi + +# populate route table +ip route flush table {{route_table_name}} +ip route add ${route_vpn_gateway} dev ${dev} src ${ifconfig_local} table {{route_table_name}} +ip route add default via ${route_vpn_gateway} table {{route_table_name}} + +# add vpn_gateway to main route table +ip route add ${route_vpn_gateway} dev ${dev} src ${ifconfig_local} + + +ip rule add from ${ifconfig_local} table {{route_table_name}} pref {{rule_pref}} + +exit 0