Add HTTP(S) proxy support #3504

Open
opened 2026-02-05 06:55:13 +03:00 by OVERLORD · 1 comment
Owner

Originally created by @LawsonHerman on GitHub (Feb 10, 2023).

Describe the Bug

I have configured BookStack with a WebHook to Microsoft Teams which worked as expected. I then introduced a Proxy Server to my network and configured the server to use the Proxy Server, which also worked as expected.

However, it appears that PHP (actually the curl extension) ignores global proxy settings if defined within Apache via ProxyRemote or environment variables. All outgoing requests to Microsoft Teams timeout as the endpoint couldn't be reached.

The problem is that the curl request in vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php (getDefaultConf) is not proxy aware.

Steps to Reproduce

  1. Create a new WebHook to Microsoft Teams that is called when a new Page is created
  2. Disallow outgoing traffic in your local Firewall
  3. Setup a proxy server
  4. Configure the proxy server in /etc/environment and/or your Apache configuration
  5. Create a new Page, see a timeout error

Alternatively:

<?php
        // create curl resource
        $ch = curl_init();

        // uncomment below to use a proxy server
        //curl_setopt($handle, CURLOPT_PROXY, "http://IP-ADDRESSOFPROXY:3128"); 
        //curl_setopt($handle, CURLOPT_PROXYUSERPWD, "username:password");

        // set url
        curl_setopt($ch, CURLOPT_URL, "https://google.com/");
        //return the transfer as a string
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        // $output contains the output string
        $output = curl_exec($ch);
        // close curl resource to free up system resources
        curl_close($ch);      

?>

Expected Behaviour

The webhook should be called

Screenshots or Additional Context

In vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php we can change the default configuration of Guzzle to include a proxy server (see lines after // Manually set curl proxy configuration):

    /**
     * @return array<int|string, mixed>
     */
    private function getDefaultConf(EasyHandle $easy): array
    {
        $conf = [
            '_headers'              => $easy->request->getHeaders(),
            \CURLOPT_CUSTOMREQUEST  => $easy->request->getMethod(),
            \CURLOPT_URL            => (string) $easy->request->getUri()->withFragment(''),
            \CURLOPT_RETURNTRANSFER => false,
            \CURLOPT_HEADER         => false,
            \CURLOPT_CONNECTTIMEOUT => 150,

            // Manually set curl proxy configuration
            \CURLOPT_PROXY => "http://IP-ADDRESSOFPROXY:3128",
            \CURLOPT_PROXYUSERPWD => "username:password",
        ];

        if (\defined('CURLOPT_PROTOCOLS')) {
            $conf[\CURLOPT_PROTOCOLS] = \CURLPROTO_HTTP | \CURLPROTO_HTTPS;
        }

        $version = $easy->request->getProtocolVersion();
        if ($version == 1.1) {
            $conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_1_1;
        } elseif ($version == 2.0) {
            $conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_2_0;
        } else {
            $conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_1_0;
        }

        return $conf;
    }

Browser Details

No response

Exact BookStack Version

v23.01.1

PHP Version

8.1.2

Hosting Environment

  • Ubuntu 22.04.01 with outgoing traffic on port 80/443 blocked towards the internet
  • HTTP Proxy Server (Port 3128)
Originally created by @LawsonHerman on GitHub (Feb 10, 2023). ### Describe the Bug I have configured BookStack with a WebHook to Microsoft Teams which worked as expected. I then introduced a Proxy Server to my network and configured the server to use the Proxy Server, which also worked as expected. However, it appears that PHP (actually the curl extension) ignores global proxy settings if defined within Apache via `ProxyRemote` or environment variables. All outgoing requests to Microsoft Teams timeout as the endpoint couldn't be reached. The problem is that the curl request in `vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php` (`getDefaultConf`) is not proxy aware. ### Steps to Reproduce 1. Create a new WebHook to Microsoft Teams that is called when a new Page is created 2. Disallow outgoing traffic in your local Firewall 3. Setup a proxy server 4. Configure the proxy server in /etc/environment and/or your Apache configuration 5. Create a new Page, see a timeout error Alternatively: ``` <?php // create curl resource $ch = curl_init(); // uncomment below to use a proxy server //curl_setopt($handle, CURLOPT_PROXY, "http://IP-ADDRESSOFPROXY:3128"); //curl_setopt($handle, CURLOPT_PROXYUSERPWD, "username:password"); // set url curl_setopt($ch, CURLOPT_URL, "https://google.com/"); //return the transfer as a string curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // $output contains the output string $output = curl_exec($ch); // close curl resource to free up system resources curl_close($ch); ?> ``` ### Expected Behaviour The webhook should be called ### Screenshots or Additional Context In `vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php` we can change the default configuration of Guzzle to include a proxy server (see lines after `// Manually set curl proxy configuration`): ```php /** * @return array<int|string, mixed> */ private function getDefaultConf(EasyHandle $easy): array { $conf = [ '_headers' => $easy->request->getHeaders(), \CURLOPT_CUSTOMREQUEST => $easy->request->getMethod(), \CURLOPT_URL => (string) $easy->request->getUri()->withFragment(''), \CURLOPT_RETURNTRANSFER => false, \CURLOPT_HEADER => false, \CURLOPT_CONNECTTIMEOUT => 150, // Manually set curl proxy configuration \CURLOPT_PROXY => "http://IP-ADDRESSOFPROXY:3128", \CURLOPT_PROXYUSERPWD => "username:password", ]; if (\defined('CURLOPT_PROTOCOLS')) { $conf[\CURLOPT_PROTOCOLS] = \CURLPROTO_HTTP | \CURLPROTO_HTTPS; } $version = $easy->request->getProtocolVersion(); if ($version == 1.1) { $conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_1_1; } elseif ($version == 2.0) { $conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_2_0; } else { $conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_1_0; } return $conf; } ``` ### Browser Details _No response_ ### Exact BookStack Version v23.01.1 ### PHP Version 8.1.2 ### Hosting Environment * Ubuntu 22.04.01 with outgoing traffic on port 80/443 blocked towards the internet * HTTP Proxy Server (Port 3128)
OVERLORD added the 🔨 Feature Request🏭 Back-End labels 2026-02-05 06:55:13 +03:00
Author
Owner

@ssddanbrown commented on GitHub (Feb 10, 2023):

Thanks @LawsonHerman for the report.
Yeah, we don't explicitly support proxy systems within BookStack.
There's quite a few other outbound http requests which would encounter the same.

I'll recategorize this as a feature request since it's not a break/bug in existing supported logic.

Devnotes

There are security issues around just accepting common env variable values, would need careful implementation:

@ssddanbrown commented on GitHub (Feb 10, 2023): Thanks @LawsonHerman for the report. Yeah, we don't explicitly support proxy systems within BookStack. There's quite a few other outbound http requests which would encounter the same. I'll recategorize this as a feature request since it's not a break/bug in existing supported logic. ### Devnotes There are security issues around just accepting common env variable values, would need careful implementation: - https://docs.guzzlephp.org/en/stable/quickstart.html?highlight=HTTP_PROXY#environment-variables - https://httpoxy.org/
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/BookStack#3504