Example #1
0
def pac_context_for_url(url="https://www.actlab.org/", proxy_auth=None):
    """
    This context manager provides a simple way to add rudimentary PAC functionality
    to code that cannot be modified to use :class:`PACSession`,
    but obeys the ``HTTP_PROXY`` and ``HTTPS_PROXY`` environment variables.

    Upon entering this context, PAC discovery occurs with default parameters.
    If a PAC is found, then it's asked for the proxy to use for the given URL.
    The proxy environment variables are then set accordingly.

    Note that this provides a very simplified PAC experience that's insufficient for some scenarios.

    :param url: Consult the PAC for the proxy to use for this URL. Default is "https://www.actlab.org/"
    :param requests.auth.HTTPProxyAuth proxy_auth: Username and password proxy authentication.
    """
    prev_http_proxy, prev_https_proxy = os.environ.get(
        'HTTP_PROXY'), os.environ.get('HTTPS_PROXY')
    pac = pypac.get_pac()
    if pac:
        resolver = pypac.ProxyResolver(pac, proxy_auth=proxy_auth)
        proxies = resolver.get_proxy_for_requests(url)
        # Cannot set None for environ. (#27)
        os.environ['HTTP_PROXY'] = proxies.get('http') or ''
        os.environ['HTTPS_PROXY'] = proxies.get('https') or ''
    yield
    if prev_http_proxy:
        os.environ['HTTP_PROXY'] = prev_http_proxy
    elif 'HTTP_PROXY' in os.environ:
        del os.environ['HTTP_PROXY']
    if prev_https_proxy:
        os.environ['HTTPS_PROXY'] = prev_https_proxy
    elif 'HTTPS_PROXY' in os.environ:
        del os.environ['HTTPS_PROXY']
Example #2
0
 def __init__(self, pac_url: str = None, js: str = None, **kwargs: Any) -> None:
     super().__init__(**kwargs)
     if pac_url and "://" not in pac_url:
         pac_url = "http://" + pac_url
     self.pac_url = pac_url
     self._js = js
     self._pac_file = get_pac(
         url=pac_url,
         js=js,
         allowed_content_types=[
             "application/octet-stream",
             "application/x-ns-proxy-autoconfig",
             "application/x-javascript-config",
         ],
     )
     self._resolver = ProxyResolver(self._pac_file)
Example #3
0
 def __init__(self,
              pac_url: str = None,
              js: str = None,
              **kwargs: Any) -> None:
     super().__init__(**kwargs)
     if pac_url and "://" not in pac_url:
         pac_url = "http://" + pac_url
     self.pac_url = pac_url
     self._pac_file = get_pac(
         url=pac_url,
         js=js,
         allowed_content_types=[
             "application/octet-stream",
             "application/x-ns-proxy-autoconfig",
             "application/x-javascript-config",
         ],
     )
     self._resolver = ProxyResolver(self._pac_file)
Example #4
0
    def __init__(self, *, url: str = "", pac_url: str = "") -> None:
        args: Dict[str, Any] = {}

        if pac_url:
            # Load the PAC file as PyPAC won't do it for us
            if pac_url.startswith("file:"):
                with open(pac_url.replace("file://", "")) as pac:
                    args["js"] = pac.read()
            else:
                args["url"] = pac_url
                args["allowed_content_types"] = [
                    "application/octet-stream",
                    "application/x-ns-proxy-autoconfig",
                    "application/x-javascript-config",
                ]

        self.pac_url = pac_url
        self._pac_file = get_pac(**args)
        self._resolver = ProxyResolver(self._pac_file)
Example #5
0
def load_proxy():
    # Return if proxies specified in Px config
    # Check if need to refresh
    if (State.proxy_mode == MODE_CONFIG or
        (State.proxy_refresh is not None and time.time() - State.proxy_refresh
         < State.config.getint("settings", "proxyreload"))):
        dprint("Skip proxy refresh")
        return

    # Reset proxy server list
    State.proxy_mode = MODE_NONE
    State.proxy_server = []

    # First use pypac for WPAD or PAC config
    if "pypac" in sys.modules:
        State.pac = pypac.get_pac()
        # Fallback for file:/// URLs
        if State.pac is None:
            acu = pypac.windows.autoconfig_url_from_registry()
            if acu:
                acu = acu.replace("file:///", "")
                if ":" not in acu:
                    acu = "c:\\" + acu
                if os.path.isfile(acu):
                    dprint("Loading " + acu)
                    with open(acu, "r") as f:
                        State.pac = pypac.parser.PACFile(f.read())

    # Fall back to any manual proxies defined in Internet Options
    if State.pac is None:
        parse_proxy(",".join([
            urlparse.urlparse(i).netloc
            for i in set(urlrequest.getproxies().values())
        ]))

        if State.proxy_server:
            State.proxy_mode = MODE_MANUAL
    else:
        State.proxy_mode = MODE_PAC

    dprint("Proxy mode = " + str(State.proxy_mode))
    State.proxy_refresh = time.time()
Example #6
0
def _get_proxy_from_pac(url: str, hostname: str) -> Optional[str]:
    """
    Returns:
        proxy url to use
        "" if no proxy should be used
        `None` if no config was found
    """
    # Hack to disable check on content-type (given server might not be well
    # configured, and `get_pac` silently fails on wrong content-type by returning None)
    # Also disable WPAD protocol to retrieve PAC from DNS given it produce annoying
    # WARNING logs
    get_pac_kwargs: dict = {"from_dns": False, "allowed_content_types": {""}}

    force_proxy_pac_url = os.environ.get("http_proxy_pac") or os.environ.get(
        "HTTP_PROXY_PAC")
    if force_proxy_pac_url:
        get_pac_kwargs["url"] = force_proxy_pac_url
        logger.debug(
            "Retrieving .PAC proxy config url from `HTTP_PROXY_PAC` env var",
            pac_url=force_proxy_pac_url,
        )
    else:
        logger.debug("Retrieving .PAC proxy config url from system")

    try:
        pacfile = pypac.get_pac(**get_pac_kwargs)
    except Exception as exc:
        logger.warning("Error while retrieving .PAC proxy config",
                       exc_info=exc)
        return None

    if not pacfile:
        return None

    try:
        proxies = pacfile.find_proxy_for_url(url, hostname)
        logger.debug("Found proxies info in .PAC proxy config",
                     target_url=url,
                     proxies=proxies)
        proxies = [p.strip() for p in proxies.split(";")]
        if len(proxies) > 1:
            logger.warning(
                "Found multiple proxies info in .PAC proxy config for target, only the first one is going to be used !",
                target_url=url,
                proxies=proxies,
            )
        # We don't handle multiple proxies so keep the first correct one and pray !
        for proxy in proxies:
            if proxy in ("DIRECT", ""):
                # PAC explicitly told us not to use a proxy
                return ""
            elif proxy:
                # Should be of style `PROXY 8.8.8.8:9999`
                proxy_type, proxy_netloc = proxy.strip().split()
                proxy_type = proxy_type.upper()
                if proxy_type in ("PROXY", "HTTP"):
                    return f"http://{proxy_netloc}"
                elif proxy_type == "HTTPS":
                    return f"https://{proxy_netloc}"
                else:
                    logger.warning(
                        "Unsupported proxy type requested by .PAC proxy config",
                        proxy=proxy,
                        target_url=url,
                    )

        else:
            return None

    except Exception as exc:
        logger.warning("Error while using .PAC proxy config",
                       target_url=url,
                       exc_info=exc)
        return None
Example #7
0
def target_session(proxy):
    pac = get_pac(url=proxy, allowed_content_types=['text/plain'])
    return PACSession(pac)
Example #8
0
import os

import pypac

# PyPAC découvrira automatiquement les paramètres du fichier PAC
pac = pypac.get_pac(url='http://127.0.0.1:9000/localproxy.pac')

# On récupère le proxy associé à Cloudant (idem, on aurait pu utiliser n'importe quelle autre URL)
proxies = pac.find_proxy_for_url('https://rest.apisandbox.zuora.com',
                                 'zuora.com')
#proxies = pac.find_proxy_for_url('https://www.google.com', 'google.com')

# Ce qui retourne quelque chose comme : 'PROXY 4.5.6.7:8080; PROXY 7.8.9.10:8080'
# On prend la premier résultat :
proxy = 'http://{}/'.format(proxies.split()[1].rstrip(';'))

# On injecte les valeurs dans les variables d'environnement
os.environ['HTTP_PROXY'] = os.environ['HTTPS_PROXY'] = proxy