กรอง HTTP ใด ๆ ที่ร้องขอ URI?


10

ฉันต้องการกรอง URI คำขอ HTTP ที่ทำผ่าน HTTP API

ใช้กรณี:

  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 ร้องขอลดความเสี่ยงของการโจมตี Man-in-the-middle

ฉันค้นหา อย่างถี่ถ้วนแล้วฉันได้ศึกษารหัสหลัก ... แต่จบลงอย่าง Nacin เมื่อสองปีที่แล้ว:

ฉันคิดว่าคุณสามารถกรอง URL ของคำขอ HTTP ได้ แต่ตอนนี้ฉันหาไม่เจอ

ฉันพลาดอะไร? ใช่ฉัน :)


การเชื่อมคำตอบนี้ที่นี่สำหรับใครก็ตามที่ค้นหาการดีบัก cURL ใน WP
ไกเซอร์

คำตอบ:


9

น้อยกว่าคำตอบ แต่เพียงแค่รายการสิ่งที่ตรงจากประสบการณ์ของฉันกับมัน - บางทีคุณอาจมองข้ามบางสิ่งบางอย่าง

การดีบักคำขอและผลลัพธ์

โดยไม่ต้องขุดลึกเกินไปในกระบวนการอัปเดต แต่ WP HTTP API ใช้WP_HTTPคลาส นอกจากนี้ยังมีข้อเสนอที่ดี: ตัวแก้ไขข้อบกพร่อง

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

ที่ไหน$responseก็สามารถเป็นWP_Errorวัตถุที่อาจบอกคุณมากกว่านี้

หมายเหตุ: จากการทดสอบสั้น ๆ ตัวกรองนี้ดูเหมือนว่าจะทำงานได้เพียงบางเหตุผล (ถ้ามีเหตุผล) ถ้าคุณวางไว้ใกล้กับตำแหน่งที่คุณขอ ดังนั้นคุณอาจต้องโทรจากภายในการติดต่อกลับด้วยตัวกรองด้านล่าง

WP_HTTP อาร์กิวเมนต์คลาส

อากิวเมนต์ Classes นั้นสามารถกรองได้ แต่บางตัวก็จะถูกรีเซ็ตโดยเมธอด internals กลับไปเป็นสิ่งที่ WP คิดว่าจำเป็น

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

หนึ่งในข้อโต้แย้งคือssl_verifyซึ่งเป็นจริงโดยค่าเริ่มต้น (แต่สำหรับฉันทำให้เกิดปัญหาใหญ่เมื่ออัปเดตจาก - ตัวอย่างเช่น - GitHub) แก้ไข:หลังจากการแก้จุดบกพร่องคำขอทดสอบผมพบว่าการโต้แย้งอื่นที่มีการตั้งค่าเพื่อตรวจสอบว่า SSL trueถูกตั้งค่าให้ มันถูกเรียกว่าsslverify(โดยไม่แยกเครื่องหมายขีดล่าง) ไม่มีความคิดที่สิ่งนี้เข้ามาในเกมหากมีการใช้งานจริงหรือถูกทอดทิ้งและถ้าคุณมีโอกาสที่จะมีอิทธิพลต่อค่าของมัน ฉันพบมันโดยใช้'http_api_debug'ตัวกรอง

กำหนดเองโดยสิ้นเชิง

นอกจากนี้คุณยังสามารถ "แทนที่" เพียงแค่แทนที่ internals ทั้งหมดและไปกับการตั้งค่าแบบกำหนดเอง มีตัวกรองสำหรับสิ่งนั้น

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

ARG แรกจะต้องตั้งค่าเป็นจริง กว่าที่คุณสามารถโต้ตอบกับการขัดแย้งภายในและผลจาก$rparse_url( $url );

หนังสือมอบฉันทะ

สิ่งอื่นที่อาจใช้ได้คือทำงานทุกอย่างผ่านพร็อกซีที่กำหนดเอง wp-config.phpนี้ต้องตั้งค่าบางอย่างในของคุณ ฉันไม่เคยลองแบบนี้มาก่อน แต่ฉันก็วิ่งผ่านค่าคงที่มาระยะหนึ่งแล้วสรุปตัวอย่างบางส่วนที่ควรใช้งานได้และรวมความคิดเห็นไว้ด้วยในกรณีที่ฉันต้องการมันสักวันหนึ่ง คุณต้องกำหนดWP_PROXY_HOSTและWP_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_*ชั้นเรียนFsockopen, Streams, Curl, Proxy, ,Cookie Encodingถ้าคุณขอให้โทรกลับไปยัง'http_api_debug'-action ดังนั้นอาร์กิวเมนต์ที่สามจะบอกคุณว่าคลาสใดที่ใช้สำหรับคำขอของคุณ

ในWP_HTTP_curlชั้นเรียนคุณจะพบrequest()วิธีการ วิธีการนี้มีสองตัวกรองเพื่อสกัดกั้นพฤติกรรมของ SSL: หนึ่งสำหรับการร้องขอท้องถิ่นและหนึ่งสำหรับการร้องขอจากระยะไกล'https_local_ssl_verify' 'https_ssl_verify'WP มีแนวโน้มที่จะกำหนดlocalเป็นและสิ่งที่คุณได้รับผลตอบแทนจากlocalhostget_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' );

Sidenote: ในกรณีส่วนใหญ่WP_HTTP_curlจะถูกใช้เพื่อจัดการพร็อกซี่


1
อ่าฉันคิดว่าคุณตอบคำถามทางอ้อม: ฉันขอได้pre_http_requestยกเลิกคำขอและส่งอีกครั้งด้วย URL ที่ถูกต้อง จะลองในคืนนี้
fuxia

8

จากคำตอบที่มีประโยชน์ของ @ kaiser ฉันได้เขียนโค้ดบางส่วนที่ดูเหมือนจะทำงานได้ดี นั่นคือเหตุผลที่ฉันทำเครื่องหมายว่าเป็นคำตอบ

ให้ฉันอธิบายวิธีแก้ปัญหาของฉัน ...

ตรรกะ

เมื่อมีการร้องขอให้ส่งผ่าน API WP_Http::request()คือวิ่งผ่าน นั่นเป็นวิธีการที่ ...

@todo Refactor รหัสนี้

…ในส่วนหัว ฉันไม่เห็นด้วยเพิ่มเติม

ตอนนี้มีตัวกรองอยู่บ้าง ฉันตัดสินใจผิดpre_http_requestสำหรับความต้องการของฉัน:

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

เราได้รับสามข้อโต้แย้งที่นี่: false, $r, $url.

  • falseapply_filters()เป็นค่าตอบแทนที่คาดหวังสำหรับ หากเราส่งสิ่งอื่นกลับมา WordPress จะหยุดทันทีและคำขอเดิมจะไม่ถูกส่ง

  • $rคืออาร์เรย์ของอาร์กิวเมนต์สำหรับคำขอนั้น เราต้องเปลี่ยนสิ่งเหล่านี้ในไม่กี่นาที

  • $urlเป็น - แปลกใจ! - URL

ดังนั้นในการเรียกกลับของt5_update_wp_per_https()เราเราจะดู URL และถ้าเป็น URL ที่เราต้องการกรองเราจะพูดว่าNO to WordPress โดยไม่พูดว่า“ ไม่” ( 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 เพื่อดาวน์โหลดไฟล์ใหม่

ผมทดสอบกับสองติดตั้งท้องถิ่นเว็บไซต์เดียวและการติดตั้งหลายเว็บไซต์บน Win 7. บังคับให้มีการปรับปรุงชุดฉัน$wp_versionในwp-includes/version.phpการ1และรุ่นของ TwentyEleven 1.3ไป

ในการรับชมเครือข่ายที่ฉันใช้Wireshark : มันฟรีมันทำงานบน Windows และ Linux และมีเครื่องมือตัวกรองที่น่าประทับใจ

การดู HTTPS นั้นค่อนข้างยาก: คุณเห็นเพียงข้อมูลที่เข้ารหัส…นั่นคือแนวคิดหลังจากทั้งหมด เพื่อดูว่าปลั๊กอินของฉันทำในสิ่งที่ควรทำหรือไม่ฉันควรดูปริมาณข้อมูลที่ไม่ได้เข้ารหัสก่อนหรือไม่และจดบันทึกที่อยู่ IP ที่ใช้เชื่อมต่อกับ wordpress.org นั่นเป็นบางครั้ง72.233.56.138 ไม่น่าแปลกใจที่มี load balancer และเครื่องมืออื่น ๆ มากมายดังนั้นเราจึงไม่สามารถพึ่งพาที่อยู่IP เดียวได้72.233.56.139

จากนั้นฉันพิมพ์ip.addr == 72.233.56.138ลงในหน้ากากตัวกรองเปิดใช้งานปลั๊กอินไปที่wp-admin/update-core.phpและดูการจราจรใน Wireshark เส้นสีเขียวคือคำขอในข้อความล้วน - สิ่งที่เราไม่ต้องการ เส้นสีแดงและสีดำเป็นสัญลักษณ์ของความสำเร็จ

Wireshark

การตรวจสอบการอัปเดตเป็นไปด้วยดี: พบรุ่น "ใหม่กว่า" การปรับปรุงจริงสำหรับชุดรูปแบบและแกนก็ใช้ได้เช่นกัน สิ่งที่ฉันต้องการ

และยัง ... ที่อาจจะง่ายขึ้นหากมีตัวกรองอย่างง่ายสำหรับ URL


1
+1 สำหรับ/* /**/เพียงเพราะมันเป็นอัจฉริยะ และ (ถ้าทำได้) อีก +1 สำหรับ Charles Bronson และควรมี +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 ตัวแปรโกลบอล $ replace_url ควรถูกตั้งค่าเป็น NULL หลังจากใช้งานแล้ว มิฉะนั้นหลังจากการปรากฏตัวครั้งแรกของ "wordpress.org" ใน URL แล้ว URL อื่น ๆ ทั้งหมดจะถูกแทนที่
MihanEntalpo
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.