예제 #1
0
    def run(self):
        CgfwUtil.mkDirAndClear(self.param.tmpDir)
        try:
            sys.stdout = StdoutRedirector(os.path.join(self.param.tmpDir, "fpemud-cgfw.out"))
            sys.stderr = sys.stdout

            logging.getLogger().addHandler(logging.StreamHandler(sys.stderr))
            logging.getLogger().setLevel(logging.INFO)

            # check configuration
            if len(CgfwCommon.getCgfwCfgList(self.param.etcDir)) == 0:
                raise Exception("no cgfw config file")

            # create main loop
            DBusGMainLoop(set_as_default=True)
            self.param.mainloop = GLib.MainLoop()
            self.param.dbusMainObject = DbusMainObject(self.param, self)

            # write pid file
            with open(os.path.join(self.param.tmpDir, "fpemud-cgfw.pid"), "w") as f:
                f.write(str(os.getpid()))

            # modify dns server configuration
            with open("/etc/resolv.conf", "r") as f:
                self.resloveFileContent = f.read()
            self.dnsmasqProc = self._runDnsmasq()
            with open("/etc/resolv.conf", "w") as f:
                f.write("# Generated by fpemud-cgfw\n")
                f.write("nameserver 127.0.0.1\n")
            logging.info("DNS resolution path modified.")

            # run vpn client
            GObject.timeout_add_seconds(0, self._timeoutCallback)

            # start main loop
            logging.info("Mainloop begins.")
            GLib.unix_signal_add(GLib.PRIORITY_HIGH, signal.SIGINT, self._sigHandlerINT, None)
            GLib.unix_signal_add(GLib.PRIORITY_HIGH, signal.SIGTERM, self._sigHandlerTERM, None)
            GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGHUP, self._sigHandlerHUP, None)
            GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGUSR1, self._sigHandlerUSR1, None)
            self.param.mainloop.run()
            logging.info("Mainloop exits.")
        finally:
            if self.vpnClientPidWatch is not None:
                GLib.source_remove(self.vpnClientPidWatch)
            if self.vpnClientProc is not None:
                self.vpnClientProc.terminate()
                self.vpnClientProc.wait()

            # revert dns resolution path
            if self.resloveFileContent is not None:
                with open("/etc/resolv.conf", "w") as f:
                    f.write(self.resloveFileContent)
            if self.dnsmasqProc is not None:
                self.dnsmasqProc.terminate()
                self.dnsmasqProc.wait()

            logging.shutdown()
            shutil.rmtree(self.param.tmpDir)
예제 #2
0
    def _runVpnClient(self):
        assert self.vpnClientProc is None and self.vpnClientPidWatch is None

        # randomly select a config
        cgfwCfg = random.choice(CgfwCommon.getCgfwCfgList(self.param.etcDir))

        # start vpn client process
        logging.info("CGFW VPN %s establishing." % (cgfwCfg.name))
        if cgfwCfg.vtype == "pptp":
            cmd = "/usr/sbin/pppd call %s nodetach" % (cgfwCfg.name)
            self.vpnClientProc = subprocess.Popen(cmd, shell=True, universal_newlines=True)
        else:
            assert False

        # wait for the vpn interface
        time.sleep(0.1)
        while not CgfwUtil.interfaceExists(cgfwCfg.interface):
            if self.vpnClientProc.poll() is not None:
                self.vpnClientProc = None
                logging.info("CGFW VPN %s failed to establish, retry in %d seconds." % (cgfwCfg.name, self.param.retryTimeout))
                GObject.timeout_add_seconds(self.param.retryTimeout, self._timeoutCallback)
                return
            time.sleep(1.0)

        # add routes
        for ip in self.param.nameServerList:
            CgfwUtil.shell("/bin/route add -host %s dev %s" % (ip, cgfwCfg.interface), "stdout")
        for net in CgfwCommon.getPrefixList(self.param.gfwDir):
            r = net.with_netmask.split("/")
            ip = r[0]
            mask = r[1]
            CgfwUtil.shell("/bin/route add -net %s netmask %s dev %s" % (ip, mask, cgfwCfg.interface), "stdout")

        # add dns server
        # dbusObj = dbus.SystemBus().get_object('org.freedesktop.resolve1', '/org/freedesktop/resolve1')
        # ifid = CgfwUtil.getInterfaceIfIndex(cgfwCfg.interface)
        # dbusObj.SetLinkDNS(ifid, [CgfwUtil.ip2ipar("8.8.8.8"), CgfwUtil.ip2ipar("8.8.4.4")], dbus_interface="org.freedesktop.resolve1.Manager")
        # logging.info("CGFW DNS server installed.")

        # watch vpn client process
        # bad things happen if the vpn process terminates before this operation
        self.vpnClientPidWatch = GLib.child_watch_add(self.vpnClientProc.pid, self._childWatchCallback)
        self.curCgfwCfg = cgfwCfg
        logging.info("CGFW VPN %s established." % (cgfwCfg.name))
        self.param.dbusMainObject.VpnConnected(self.bDataChanged)
예제 #3
0
    def cmdUpdate(self):
        CgfwUtil.printInfo("Checking IP ranges:")
        if True:
            prefixList = CgfwCommon.getPrefixList(self.param.gfwDir)

            CgfwUtil.printInfoNoNewLine("    Checking private network...")
            priList = CgfwUtil.getReservedIpv4NetworkList()
            for net in prefixList:
                for net2 in priList:
                    if net.overlaps(net2):
                        raise CgfwCmdException("GFWed prefix %s overlaps private network %s" % (net.with_prefixlen, net2.with_prefixlen))
            print("Done.")

            CgfwUtil.printInfoNoNewLine("    Checking non-GFWed network...")
            try:
                lcmList = CgfwCommon.getLatestChinaMainLandIpv4NetworkList()
                for net in prefixList:
                    for net2 in lcmList:
                        if net.overlaps(net2):
                            raise CgfwCmdException("GFWed prefix %s overlaps non-GFWed network %s" % (net.with_prefixlen, net2.with_prefixlen))
                print("Done.")
            except Exception as e:
                if isinstance(e, CgfwCmdException):
                    raise
                else:
                    print("Failed, but however it's better to continue.")

        CgfwUtil.printInfo("Modifying configuration files:")
        for cgfwCfg in CgfwCommon.getCgfwCfgList(self.param.etcDir):
            if cgfwCfg.vtype == "pptp":
                self._syncPptpVpnScript(cgfwCfg)
            else:
                assert False

        # send signal to daemon process if exists
        try:
            with open(os.path.join(self.param.tmpDir, "fpemud-cgfw.pid")) as f:
                os.kill(int(f.read()), signal.SIGHUP)
        except:
            pass
예제 #4
0
 def cmdCheck(self):
     for cgfwCfg in CgfwCommon.getCgfwCfgList(self.param.etcDir):
         if cgfwCfg.vtype == "pptp":
             self._checkPptpVpn(cgfwCfg)
         else:
             assert False