HTTPリクエストURIをフィルタリングしますか?


10

HTTP APIを介して行われたHTTPリクエストURIをフィルタリングしたい。

ユースケース:

  1. WordPressの更新チェックはhttp://api.wordpress.org/core/version-check/1.6/に行きますが、https://api.wordpress.org/core/version-check/1.6/も機能します。これを常に使用します。
  2. 新しいWordPressファイルはhttp://wordpress.org/wordpress-3.4.2.zipから取得されますが、https://wordpress.org/wordpress-3.4.2.zipも機能します。
  3. リクエストをデバッグして、ローカルサーバーのカスタムドメインに一時的にリダイレクトしたい場合があります。
  4. 一部のプラグインは他のサーバーに要求を出しますが、外部サーバーがダウンしたときにこれらの要求を置き換えたいと思います。

修正のバグ16778詳細)がまだあるため、更新リクエストは今のところ最も重要なリクエストであり、HTTPSリクエストは中間者攻撃のリスクを低減します。

私は徹底的検索 、コアコードを調査しましたが、2年前のNacinのようになりました。

確かにHTTPリクエストのURLをフィルタリングできると思っていましたが、今は見つかりません。

私は何を取りこぼしたか?私は?:)


WPでcURLデバッグを検索する人のためにこの回答をここにリンクします
カイザー、2014年

回答:


9

答えではありませんが、私の経験から得たもののリストです。おそらく見落としているかもしれません。

リクエストとその結果のデバッグ

更新プロセスを深く掘り下げることなく、WP HTTP APIはWP_HTTPクラスを使用します。また、デバッグフックという優れた機能も提供します。

do_action( 'http_api_debug', $response, 'response', $class, $args, $url );

どこに$responseWP_Error、おそらくあなたにもっと教えてくれるオブジェクトがあります。

注:簡単なテストから、このフィルターは、(何らかの理由で)実際にリクエストを行っている場所の近くに配置した場合にのみ機能するようです。したがって、以下のフィルターのいずれかのコールバック内から呼び出す必要があるかもしれません。

WP_HTTP クラス引数

Classes引数自体はフィルター可能ですが、一部のメソッドは内部メソッドによってリセットされ、WPが必要とするものに戻ります。

apply_filters( 'http_request_args', $r, $url );

引数の1つはでssl_verify、これはデフォルトでtrueです(ただし、GitHubなどから更新する場合、私には大きな問題が発生します)。編集:テストリクエストをデバッグした後、SSLがに設定されているかどうかを確認するために設定されている別の引数を見つけましたtruesslverify(下線を区切ることなく)呼び出されます。これが実際に使用されているか放棄されているか、そしてその価値に影響を与える可能性があるかどうか、これがゲームのどこに導入されたかはわかりません。'http_api_debug'フィルターを使って見つけました。

完全にカスタム

内部全体を「単純に」オーバーライドして、カスタムセットアップを使用することもできます。そのためのフィルターがあります。

apply_filters( 'pre_http_request', false, $r, $url );

最初の引数をtrueに設定する必要があります。内部の引数$rやからの結果を操作できparse_url( $url );ます。

代理

機能する可能性のあるもう1つのことは、カスタムプロキシを介してすべてを実行することです。これには、いくつかの設定が必要wp-config.phpです。これまで試したことはありませんでしたが、定数をしばらく前に調べて、機能するはずの例をいくつかまとめ、ある日必要になった場合に備えてコメントを含めました。あなたは定義する必要がWP_PROXY_HOSTWP_PROXY_PORT分として。設定。他に何も機能せず、単にプロキシをバイパスします。

# HTTP Proxies
# Used for e.g. in Intranets
# Fixes Feeds as well
# Defines the proxy adresse.
define( 'WP_PROXY_HOST',          '127.0.84.1' );
# Defines the proxy port.
define( 'WP_PROXY_PORT',          '8080' );
# Defines the proxy username.
define( 'WP_PROXY_USERNAME',      'my_user_name' );
# Defines the proxy password.
define( 'WP_PROXY_PASSWORD',      'my_password' );
# Allows you to define some adresses which
# shouldn't be passed through a proxy.
define( 'WP_PROXY_BYPASS_HOSTS',  'localhost, www.example.com' );

編集

WP_HTTPクラスは、通常のように作用するベースクラス(異なるシナリオに拡張されます)。拡張WP_HTTP_*クラスはFsockopenStreamsCurlProxyCookieEncoding。コールバックを'http_api_debug'-actionにフックすると、3番目の引数で、要求に使用されたクラスがわかります。

WP_HTTP_curlクラスの中には、request()メソッドがあります。このメソッドは、SSL動作をインターセプトする2つのフィルターを提供します。1つはローカルリクエスト用で'https_local_ssl_verify'、もう1つはリモートリクエスト用'https_ssl_verify'です。WPは、あなたが見返りlocalとしてlocalhost何を得るかを定義するでしょうget_option( 'siteurl' );

したがって、その要求を行う直前に(または最も近い要求にフックされているコールバックから)、次のことを試してみます。

add_filter( 'https_ssl_verify', '__return_true' );

# Local requests should be checked with something like
# 'localhost' === $_SERVER['HTTP_HOST'] or similar
# add_filter( 'https_local_ssl_verify', '__return_true' );

補足:ほとんどの場合、WP_HTTP_curlプロキシの処理に使用されます。


1
ああ、あなたは私の質問に間接的に答えたと思います:にフックしpre_http_requestてリクエストをキャンセルし、正しいURLで再送信できます。今夜試してみます。
fuxia

8

@kaiserの有用な回答に基づいて、うまく機能しているように見えるコードをいくつか作成しました。それが私がそれをThe Answerとマークした理由です。

私の解決策を説明しましょう…

ロジック

APIを介して送信されたリクエストは、を介して実行されWP_Http::request()ます。それが…の方法です

@todoこのコードをリファクタリングします。

…ヘッダー内。私はこれ以上同意できませんでした。

今、いくつかのフィルターがあります。私はpre_http_request自分のニーズを誤用することにしました:

add_filter( 'pre_http_request', 't5_update_wp_per_https', 10, 3 );

ここでは3つの引数を取得しますfalse, $r, $url

  • falseの期待される戻り値ですapply_filters()。他に何かを送り返すと、WordPressはすぐに停止し、元のリクエストは送信されません。

  • $rそのリクエストの引数の配列です。これらも1分で変更する必要があります。

  • $urlです–サプライズ!– URL。

だから、私たちのコールバックでt5_update_wp_per_https()、私たちはURLを見ていない、そしてそれは我々がフィルタしたいURLであれば、我々は言うNOでワードプレスにはない(「なし」と言いますfalse)。

ここに画像の説明を入力してください

補足:次のようにすると、すべてのHTTPリクエストを防止できます。
add_filter( 'pre_http_request', '__return_true' );

代わりに、より良いURLと少し調整された引数(読みやすく$rする$argsために名前を変更)を使用して、独自のリクエストを発行します。

コード

インラインコメントをお読みください。重要です。

<?php
/**
 * Plugin Name: T5 Update WP per HTTPS
 * Description: Forces update checks and downloads for WP to use HTTPS.
 * Plugin URI:  http://wordpress.stackexchange.com/questions/72529/filter-any-http-request-uri
 * Version:     2012.11.14
 * Author:      Thomas Scholz
 * Author URI:  http://toscho.de
 * Licence:     MIT
 * License URI: http://opensource.org/licenses/MIT
 */

add_filter( 'pre_http_request', 't5_update_wp_per_https', 10, 3 );

/**
 * Force HTTPS requests for update checks and new WP version downloads.
 *
 * @wp-hook pre_http_request
 * @param   bool   $false
 * @param   array  $args
 * @param   string $url
 * @return  FALSE|array|object FALSE if everything is okay, an array of request
 *                            results or an WP_Error instance.
 */
function t5_update_wp_per_https( $false, $args, $url )
{
    // Split the URL into useful parts.
    $url_data = parse_url( $url );

    // It is already HTTPS.
    if ( 'https' === strtolower( $url_data['scheme'] ) )
        return FALSE;

    // Not our host.
    if ( FALSE === stripos( $url_data['host'], 'wordpress.org' ) )
        return FALSE;

    // Make that an HTTPS request.
    $new_url = substr_replace( $url, 'https', 0, 4 );

    // WP_Http cannot verify the wordpress.org certificate.
    $args['sslverify'] = FALSE;

    // It is slow. We wait at least 30 seconds.
    30 > $args['timeout'] and $args['timeout'] = 30;

    // Get an instance of WP_Http.
    $http    = _wp_http_get_object();

    // Get the result.
    $result = $http->request( $new_url, $args );

    /* prepend this line with a '#' to debug like a boss.
    print '<pre>'
    . htmlspecialchars( print_r( $result, TRUE ), ENT_QUOTES, 'utf-8', FALSE )
    . '</pre>';
    die();
    /**/

    return $result;
}

テスト

そのプラグインなしでWordPressを使用しました:

  • http://api.wordpress.org/core/version-check/1.6/ 更新チェック、および
  • http://wordpress.org/wordpress-3.4.2.zip 新しいファイルをダウンロードします。

私は設定の更新を強制するには2つのローカルインストール、単一サイトとのWin 7のマルチサイトの設定とそれをテスト$wp_versionwp-includes/version.php1とTwentyElevenのバージョンにします1.3

Wiresharkを使用してネットワークトラフィックを監視する:無料で、WindowsとLinuxで動作し、印象的なフィルターツールをいくつか提供しています。

HTTPSの監視は少し難しいです。暗号化されたデータが表示されるだけです。プラグインが本来の動作をするかどうかを確認するために、暗号化されていないトラフィックを最初に監視し、wordpress.orgへの接続に使用されているIPアドレスを書き留めました。それは72.233.56.138時々だった72.233.56.139
当然のことですが、ロードバランサーと他の多くのツールがあるため、1つの IPアドレスに依存することはできません。

次にip.addr == 72.233.56.138、フィルターマスクを入力し、プラグインをアクティブにしてwp-admin/update-core.php、Wiresharkのトラフィックを監視しました。緑の線はプレーンテキストでの要求です。まさに私たちが望まないものです。赤と黒の線は成功の印です。

Wireshark

アップデートチェックはうまくいきました:それは「より新しい」バージョンを見つけました。テーマとコアの実際の更新もうまくいきました。まさに私が必要としたもの。

それでも…URLの単純なフィルターがあれば、もっと簡単になるでしょう。


1
+1です/* /**/。天才だからです。そして(もし可能なら)チャールズ・ブロンソンのための別の+1。そして、詳細な説明、コメント、スクリーンショットのための別の+1があるはずです。
カイザー、

3
    add_filter('http_request_args', 'http_request_args_custom', 10,2);
    function http_request_args_custom($request,$url){
            if (strpos($url, 'wordpress.org') !== false){
                    global $replaced_url;
                    $replaced_url = 'http://wordpress.local';
            }
            return $request;
    }

    add_action('http_api_curl', 'http_api_curl_custom');
    function http_api_curl_custom(&$handle){
            global $replaced_url;
            if (!is_null($replaced_url))
                    curl_setopt( $handle, CURLOPT_URL, $replaced_url);
    }

    $http = new WP_Http();
    $response = $http->request('http://wordpress.org', array());

    var_dump($response);

1
このコード例の関数http_api_curl_customでは、グローバル変数$ replaced_urlは、使用後にNULLに設定する必要があることに注意してください。それ以外の場合、URLで最初に「wordpress.org」が出現した後、他のすべてのURLが置き換えられます。
MihanEntalpo
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.