WordPress.org

Make WordPress Core

Opened 8 years ago

Closed 7 years ago

#3082 closed defect (bug) (duplicate)

Wordpress can't make outbound POST and GET requests when its behind a proxy

Reported by: the_dead_one Owned by:
Milestone: Priority: normal
Severity: normal Version: 2.0.3
Component: General Keywords: proxy Dashboard Akismet IXR
Focuses: Cc:

Description

I have wordpress installed on a server that is behind a proxy. Both the server and the proxy allow outbound HTTP requests. However there is no support or options for using a proxy. This affects outbound pings, dashboard feeds, akismet plugin and several functions used by other plugins.

The reason it doesn't work is that PHP's fopen and fsockopen do not support requests via proxies and must be modified to handle proxies. All requests to fopen and/or fsockopen would have to be updated to support the use of a proxy if one exists.

I've applied several hacks to the wordpress core to get it to work, however they would need to be scaled up to become a patch as they are not compatible when there is no proxy and they do no support proxy authentication. (Originally I documented them here).

These hacks do not cover all instances of fopen and fsockopen in the codebase, so more extensive testing may need to be done.

The Dashboard feeds are not updated through a proxy. This is the most trivial to fix as class-snoopy.php is the only file to support proxy. In 'wp-include/class-snoopy.php', set the 'proxy_host' variable to your proxy host and 'proxy_port' variable to your proxy port. Set '_isproxy' to "true".

To get Akismet to work, in 'wp-content/plugins/akismet.php', modify the function ksd_http_post like this but replacing your_proxy_host with the proxy address and your_proxy_port with the port of the proxy.

// Returns array with headers in $response[0] and entity in $response[1]
function ksd_http_post($request, $host, $path, $port = 80) {
        global $ksd_user_agent;
 
        //$http_request  = "POST $path HTTP/1.0\r\n";
        //$http_request .= "Host: $host\r\n";
        $http_request  = "POST http://$host$path HTTP/1.0\r\n";
        $http_request .= "Host: http://$host\r\n";
        $http_request .= "Content-Type: application/x-www-form-urlencoded; charset=" . get_settings('blog_charset') . "\r\n";
        $http_request .= "Content-Length: " . strlen($request) . "\r\n";
        $http_request .= "User-Agent: $ksd_user_agent\r\n";
        $http_request .= "\r\n";
        $http_request .= $request;
        $response = '';
 
        //if( false !== ( $fs = @fsockopen($host, $port, $errno, $errstr, 10) ) ) {
        if( false !== ( $fs = @fsockopen('your_proxy_host', your_proxy_port, $errno, $errstr, 10) ) ) {
                fwrite($fs, $http_request);
 
                while ( !feof($fs) )
                        $response .= fgets($fs, 1160); // One TCP-IP packet
                fclose($fs);
                $response = explode("\r\n\r\n", $response, 2);
        }
        return $response;
}

I've found class-IXR.php must also be updated. I discovered this while trying to get a plugin to work. In 'class-IXR.php', search for 'fsockopen'. Just above the first refernce to it, modify the '$request' string like this, but replacing your_proxy_host with the proxy address and your_proxy_port with the port of the proxy:

 $request  = "POST http://{$this->server}{$this->path} HTTP/1.0$r";
 $request .= "Host: http://{$this->server}$r";
 $request .= "Content-Type: text/xml$r";
 $request .= "User-Agent: {$this->useragent}$r";
 $request .= "Content-length: {$length}$r$r";
 $request .= $xml;

Then below that, modify the 'fsockopen' call like this:

 if ($this->timeout) {
  //$fp = @fsockopen($this->server, $this->port, $errno, $errstr, $this->timeout);
  $fp = @fsockopen('your_proxy_host', your_proxy_port, $errno, $errstr, $this->timeout);
 } else {
  //$fp = @fsockopen($this->server, $this->port, $errno, $errstr);
  $fp = @fsockopen('your_proxy_host', your_proxy_port, $errno, $errstr);
 }

Also I've found functions.php must also be updated. I discovered this while trying to get another plugin to work. In 'wp-includes/functions.php', modify thefunction 'wp_remote_fopen' as below, but replacing your_proxy_host with the proxy address and your_proxy_port with the port of the proxy.

  function wp_remote_fopen( $uri ) {
        if ( ini_get('allow_url_fopen') ) {
                /*$fp = fopen( $uri, 'r' );
                if ( !$fp )
                        return false;
                $linea = '';
                while( $remote_read = fread($fp, 4096) )
                        $linea .= $remote_read;
                fclose($fp);
                return $linea;*/
 
                $proxy_fp = fsockopen('your_proxy_host','your_proxy_port');
                if ( !$proxy_fp )
                        return false;
                fputs($proxy_fp, "GET $uri HTTP/1.0\r\nHost: your_proxy_host\r\n\r$
                while(!feof($proxy_fp))
                        $proxy_cont .= fread($proxy_fp,4096);
                fclose($proxy_fp);
               $proxy_cont = substr($proxy_cont, strpos($proxy_cont,"\r\n\r\n")$
        } else if ( function_exists('curl_init') ) {

Change History (1)

comment:1 Nazgul7 years ago

  • Resolution set to duplicate
  • Status changed from new to closed

Closing as duplicate of #4011 as that one has patches attached.

Note: See TracTickets for help on using tickets.