WordPress как на ладони
rgbcode is looking for WordPress developers.

Как работают Пинги, Трэкбэки в WordPress — уведомления в файл xmlrpc.php

В этом статье поговорим про пинги (trackback, pingback) в WordPress, как они устроены, чем отличаются, как работают и как использовать эффективно их использовать.

Trackbacks и pingbacks - это способы коммуникации между сайтами WordPress. Они существуют с первых дней появления WordPress, но очень немногие пользователи знают об этих функциях.

Trackbacks и Pingbacks

В WP есть два вида уведомлений о том, что кто-то сослался на вашу статью (этим кто-то может быть и ваш сайт, когда вы ссылаетесь на статью другого сайта):

Pingback

Автоматическое уведомление. Не отправляют никакого содержимого.

Это когда ваш сайт автоматически уведомляет "другой сайт" при публикации записи, о том, что в контенте записи есть ссылка на "другой сайт". При таком уведомлении ваш сайт автоматически отправляет пинг, а другой сайт получает этот пинг в виде комментария с типом comment_type = pingback.

Trackback

Ручное уведомление. Отправляют выдержку из контента поста.

При таком уведомлении вы должны вручную указать URL статьи на которую хотите отправить уведомление, а другой сайт получает это уведомление в виде комментария с типом comment_type = trackback.

Отправить Trackback, можно со страницы редактирования поста.

Чем отличаются Trackbacks и Pingbacks?

Из описания выше видно, что и то и другое делает примерно одно и то же, но все же имеют ряд отличий:

  1. Trackbacks отправляются вручную, а Pingbacks - автоматически.

  2. Pingbacks не отправляют никакого контента, в то время как trackbacks сопровождаются выдержкой из контента.

  3. Используются разные технологии отправки и получения запроса.

Настройка Trackbacks и Pingbacks?

В WP включить/отключить получение/отправку уведомлений можно на странице Настройки → Обсуждение (Settings → Discussion):

Как работают уведомления (пинги)

Тут два возможных сценария:

1) Ваш сайт отправляет пинг запрос на другой сайт

Pingback

При публикации поста ВП проверят надо ли уведомлять упомянутые в посте сайты. Т.е. он смотрит включена ли опция default_pingback_flag. Если включена, то собирает ссылки из поста и по каждой проделывает следующие операции:

  • Проходит по ссылке, и проверяет наличие x-pingback: в HTTP заголовке. Если он там есть, то отправляет на УРЛ, указанный в этом заголовке, уведомление. Уведомление тут - это HTTP запрос с POST параметрами на указанный URL.

    Для ВП такой URL смотрит на файл xmlrpc.php. Там работает огромный класс wp_xmlrpc_server{}. В классе разделяются запросы, для которых нужна авторизация и не нужна. Для такого пинг уведомления авторизация не нужна. Поэтому, если например, отключить xmlrpc через фильтр:

    // отключает XML-RPC методы которые требуют авторизацию
    add_filter( 'xmlrpc_enabled', '__return_false' );

    То уведомления (трекбеки) все равно будут работать!

  • Если заголовок x-pingback: не найден, то ВП ищет дальше: получает HTML и ищет там метатег rel="pingback". Если нашел - делает все тоже самое: отправляет уведомление по указанному в метатеге URL.

    Из коробки ВП не добавляет этот метатег в HEAD темы, обычно он добавляется самой темой. Т.е. его нужно прописать вручную, если надо. Выглядит он так:

    <link rel="pingback" href="<?php bloginfo( 'pingback_url' ); ?>">

Trackback

При публикации/обновлении поста проверяется поле trackback_url:

Если оно указано, то оно будет добавлено в поле to_ping таблицы wp_posts, в котором хранятся ссылки на сайты, которые нужно уведомить. Операция уведомления произойдет позднее по крону читайте ниже. Если коротко - для каждого поста сработает функция do_trackbacks().

2) Ваш сайт получает пинг запрос с другого сайта

В настройках сайта (картинка выше), отправка уведомлений со своего сайта и получение уведомлений - это отдельные опции, а значит они друг от друга не зависят и работают сами по себе. Т.е. можно отключить пинги, но оставить трэкбэки или наоборот.

Pingback

Уведомления приходят в файл /xmlrpc.php - он их и обрабатывает:

  • Сначала проверяет опцию default_ping_status — разрешено ли на сайте вообще получать уведомления.

  • А затем находит упомянутый пост и проверяет открыты ли для него уведомления. Делается это функцией get_default_comment_status(), в частности, проверяется значение поля ping_status у записи, которое может быть: open или closed.

  • Если уведомления открыты, то к указанной записи публикуется комментарий с типом comment_type = 'pingback'.

Trackback

Трэкбэки обрабатывает файл /wp-trackback.php.

Трэкбэк комментарий имеет тип comment_type = 'trackback'.

Для чего еще нужен файл xmlrpc.php

Файл xmlrpc.php позволяет управлять сайтом удаленно. Не знаю, пользуется ли этим кто-то сегодня.

Для такого управления есть специальные программы, например «Windows Live Writer», «Open Live Writer» и другие. С помощью них можно публиковать посты и загружать фотки на сайт удаленно. Например, с компьютера можно публиковать посты на разные сайты (для этого нужно знать логин и пароль пользователя с правами публикации).

Спам через уведомления (пинги)

Так как для отправки уведомлений нужно всего лишь отправить запрос, спамеры любят это дело. Делается это очень просто: берем домен сайта, дописываем к нему /xmlrpc.php и отправляем заготовленный POST запрос. Причем запрос будет одинаковый для всех сайтов, поэтому спамить таким образом очень просто.

Так, если у вас на сайте в комментариях выводятся уведомления со ссылкой на сайт того, кто отправил это уведомление - спамер получит обратную ссылку на свой сайт. По этой причине многие отключают уведомления.

Однако такое отключение просто не обрабатывает запросы. Но если спамеры начнут отправлять множество запросов, то это может влиять на сервер (создавать лишнюю нагрузку), получится что-то типа непреднамеренной дос атаки. Впрочем, такое, насколько я знаю, редкость.

В случае такой нагрузки от спамеров, можно полностью закрыть доступ к файлу /xmlrpc.php через файл .htaccess.

# Закрываем доступ к файлу
<FilesMatch "xmlrpc.php">
Order Deny,Allow
Deny from all
</FilesMatch>

Для nginx это делается так:

location = /xmlrpc.php {
	deny all;
}

Такое закрытие полностью «вырубает» все возможности уведомлений, тут уже можно больше ничего не делать.

Обращаю внимание еще раз! Следующее отключение xmlrpc не отключает обработку уведомлений, а отключает возможность управлять сайтом удаленно!

// отключает XML-RPC методы которые требуют авторизацию
add_filter( 'xmlrpc_enabled', '__return_false' );

Уведомления для типов записей

Для постоянных страниц (записей типа page) обработка уведомлений от других сайтов отключена жестко в коде.

Для других типов записей, уведомления можно включит или отключить отдельно на странице редактирования записи:

При регистрации типа записи в параметре supports функции register_post_type(), нужно указать поддержку трэкбеков:

'supports' => array( 'title', 'editor', 'trackbacks' ),

Иначе ping_status у новых записей по умолчанию будет closed и уведомление со ссылкой на эту запись этого типа не будет обрабатываться.

Стоит ли отключать пинги в WordPress

Я думаю, что не стоит, все-таки интересно и может быть даже полезно знать, кто и на какую статью вашего сайта ссылается.

Однако, обязательно нужно проверять есть ли обратная ссылка на ваш сайт в статье, которая упомянута в уведомлении. WordPress этого не делает по умолчанию, а зря!

Чтобы включить такую проверку можете установить мой плагин антиспама Kama Spamblock

Ну, или использовать такой код в файле functions.php:

## проверка ссылки на этот сайт при обработке трекбэков (пингов)
add_action( 'preprocess_comment', 'trackbacks_check_protect', 0 );

function trackbacks_check_protect( $commentdata ){

	if( ! in_array( $commentdata['comment_type'], [ 'trackback', 'pingback' ] ) ){
		return;
	}

	$external_html = wp_remote_retrieve_body( wp_remote_get( $commentdata['comment_author_url'] ) );

	// стоп, если нет ссылки на нас
	if( ! preg_match('~<a[^>]+href=[\'"](https?:)?//'. preg_quote( parse_url( home_url(), PHP_URL_HOST ) ) .'~si', $external_html) ){
		die( 'no backlink...' );
	}

}

Как это работает (шаг за шагом в коде)

Пинги со статьи вашего сайта отправляются кроном, схема такая:

1 шаг (создание крон задачи)

На хук publish_post, зацеплена функция _publish_post_hook():

add_action( 'publish_post', '_publish_post_hook', 5, 1 );

Таким образом, при публикации/обновлении опубликованного поста, срабатывает функция _publish_post_hook(), которая добавляет специальные метаполя и Крон задачу:

...
	if ( get_option('default_pingback_flag') ) {
		add_post_meta( $post_id, '_pingme', '1' );
	}
	add_post_meta( $post_id, '_encloseme', '1' );

	if ( ! wp_next_scheduled( 'do_pings' ) ) {
		wp_schedule_single_event( time(), 'do_pings' );
	}
...
2 шаг (крон)

Далее при выполнении крон-задачи срабатывает функция do_all_pings():

add_action( 'do_pings', 'do_all_pings', 10, 1 );

Эта функция запускает хук do_all_pings, на котором по умолчанию висят 4 функции:

add_action( 'do_all_pings', 'do_all_pingbacks', 10, 0 );
add_action( 'do_all_pings', 'do_all_enclosures', 10, 0 );
add_action( 'do_all_pings', 'do_all_trackbacks', 10, 0 );
add_action( 'do_all_pings', 'generic_ping', 10, 0 );
do_all_pingbacks() Performs all pingbacks.
do_all_enclosures() Performs all enclosures.
do_all_trackbacks() Performs all trackbacks.
generic_ping() Sends pings to all of the ping site services.

С версии WP 5.6 код функции был разбит на эти 4 функции. До этого код выполнял множество разных операций разом. Старое описание кода (в нем видно что делает каждая функция выше):

  1. Cобирает все посты с установленными метаполями и запускает для каждого из них функцию:

    • для метаполя _pingme - pingback( $post_content, $post_id ).
    • для метаполя _encloseme - do_enclose( null, $post_id ). Это отдельная логика встраивания аудио и видео из контента не относится к пингам. Такие встраивания добавляются в RSS ленту в тег:

      <enclosure url="http://example.com/file.mp3" length="123456789" type="audio/mpeg" />
  2. Также собирает все опубликованные посты status=publish AND to_ping != '' (в to_ping там обычно находятся ссылки из контента, которые нужно уведомить что они использовались в посте) и для каждого поста запускает функцию:

  3. Отправляет пинги на сайты, которые нужно пинговать (указанные в настройках). За эту операцию отвечает функция generic_ping().

Как отключить/запретить XML-RPC запросы

Для начала повторюсь, что на файл xmlrpc.php делаются запросы, которые не требуют авторизации (пинги) и которые требуют (публикация контента на сайте).

Поэтому полностью отключать этот файл не рекомендуется, можно отключить только ту часть логики, которая требует авторизацию. Делается одной строчкой через хук xmlrpc_enabled:

// отключает XML-RPC методы, которые требуют авторизацию
add_filter( 'xmlrpc_enabled', '__return_false' );
3 комментария
    Войти