обратный_прокси
Перенаправляет запросы к одному или нескольким бэкендам с настраиваемыми параметрами транспорта, балансировки нагрузки, проверки работоспособности, изменения запроса и буферизации.
- Синтаксис
- Потоки
- Балансировка нагрузки
- Потоковая передача
- Заголовки
- Переопределения
- Транспортные средства
- Перехват ответов
- Примеры
Синтаксис
reverse_proxy [<matcher>] [<upstreams...>] { # backends
to <upstreams...>
dynamic <module> ... # load balancing
lb_policy <name> [<options...>]
lb_retries <retries>
lb_try_duration <duration>
lb_try_interval <interval>
lb_retry_match <request-matcher> # active health checking
health_uri <uri>
health_upstream <ip:port>
health_port <port>
health_interval <interval>
health_passes <num>
health_fails <num>
health_timeout <duration>
health_status <status>
health_body <regexp>
health_follow_redirects
health_headers {
<field> [<values...>]
} # passive health checking
fail_duration <duration>
max_fails <num>
unhealthy_status <status>
unhealthy_latency <duration>
unhealthy_request_count <num> # streaming
flush_interval <duration>
request_buffers <size>
response_buffers <size>
stream_timeout <duration>
stream_close_delay <duration> # request/header manipulation
trusted_proxies [private_ranges] <ranges...>
header_up [+|-]<field> [<value|regexp> [<replacement>]]
header_down [+|-]<field> [<value|regexp> [<replacement>]]
method <method>
rewrite <to> # round trip
transport <name> {
...
} # optionally intercept responses from upstream
@name {
status <code...>
header <field> [<value>]
}
replace_status [<matcher>] <status_code>
handle_response [<matcher>] {
<directives...> # special directives only available in handle_response
copy_response [<matcher>] [<status>] {
status <status>
}
copy_response_headers [<matcher>] {
include <fields...>
exclude <fields...>
}
}
}
Потоки
- <upstreams...> — список потоков (бэкэндов), к которым следует перенаправить.
- to — альтернативный способ указать список потоков, по одному (или несколько) на строке.
- dynamic — настраивает модуль динамических потоков. Это позволяет динамически получать список потоков для каждого запроса. См. динамические потоки ниже для описания стандартных модулей динамических потоков. Динамические потоки извлекаются на каждой итерации цикла проксирования (т. е. потенциально несколько раз за запрос, если включены повторные попытки балансировки нагрузки), и будут предпочтительнее статических потоков. При возникновении ошибки прокси будет переключаться на использование любых статически настроенных потоков.
Адреса потоков
Статические адреса потоков могут принимать вид URL, содержащего только схему и хост/порт, или обычный адрес сети Caddy. Действительные примеры:
localhost:4000127.0.0.1:4000[::1]:4000http://localhost:4000https://example.comh2c://127.0.0.1example.comunix//var/php.sockunix+h2c//var/grpc.socklocalhost:8001-8006[fe80::ea9f:80ff:fe46:cbfd%eth0]:443
По умолчанию подключения устанавливаются к потоку по протоколу HTTP без шифрования. При использовании формы URL, схема может быть использована для установки некоторых transport значений по умолчанию в качестве сокращения.
-
Использование
https://в качестве схемы будет использоватьhttpтранспорт сtls, включённым.Кроме того, вам может потребоваться переопределить заголовок
Hostтаким образом, чтобы он соответствовал значению TLS SNI, которое используется серверами для маршрутизации и выбора сертификата. Подробнее см. раздел HTTPS ниже. -
Использование
h2c://в качестве схемы будет использоватьhttpтранспорт с версиями HTTP, установленными для разрешения явных соединений HTTP/2. -
Использование
http://в качестве схемы эквивалентно пропуску схемы, так как HTTP уже является значением по умолчанию. Этот синтаксис включен для симметрии с другими сокращениями схемы.
Схемы не могут быть смешаны, так как они изменяют общие настройки транспорта (транспорт с включённым TLS не может содержать как HTTPS, так и HTTP без шифрования). Любые явные настройки транспорта не будут переписаны, и пропуск схем или использование других портов не будет подразумевать определённый транспорт.
При использовании IPv6 с зоной (например, адресов связи с локальной зоной с определённым сетевым интерфейсом), схема не может быть использована в качестве сокращения, поскольку % приведёт к ошибке разбора URL; настройте транспорт явно вместо этого.
При использовании формы адреса сети тип сети указывается как префикс к адресу потока. Это не может быть объединено со схемой URL. В качестве специального случая, unix+h2c/ поддерживается как сокращение для unix/ сети плюс те же эффекты, что и h2c:// схема. Диапазоны портов поддерживаются как сокращение, которое расширяется до нескольких потоков с одинаковым хостом.
Адреса потоков не могут содержать пути или строки запроса, так как это подразумевает одновременное переписывание запроса во время проксирования, что не определено и не поддерживается. Используйте директиву rewrite в случае необходимости.
Если адрес не является URL (т. е. не имеет схемы), то можно использовать заменители, но это делает поток динамически статическим, что означает, что потенциально многие различные бэкэнды действуют как один статический поток с точки зрения проверок работоспособности и балансировки нагрузки. Рекомендуется использовать модуль динамических потоков вместо этого, если это возможно. При использовании замен необходимо включить порт (либо через замену замены, либо как статический суффикс к адресу).
Динамические потоки
Обратный прокси Caddy поставляется со стандартными модулями динамических потоков. Обратите внимание, что использование динамических потоков влечёт последствия для балансировки нагрузки и проверок работоспособности, в зависимости от конкретной конфигурации политики: активные проверки работоспособности не выполняются для динамических потоков; и балансировка нагрузки и пассивные проверки работоспособности лучше всего выполняются, если список потоков относительно стабилен и согласован (особенно с циклическим обходом). В идеале, модули динамических потоков возвращают только здоровые и работоспособные бэкэнды.
SRV
Извлекает потоки из записей SRV DNS.
dynamic srv [<full_name>] {
service <service>
proto <proto>
name <name>
refresh <interval>
resolvers <ip...>
dial_timeout <duration>
dial_fallback_delay <duration>
}
-
<full_name> — полное доменное имя записи для поиска (т. е.
_service._proto.name). - service — компонент службы полного имени.
-
proto — компонент протокола полного имени. Либо
tcp, либоudp. -
name — компонент имени. Или, если
serviceиprotoпусты, полное доменное имя для запроса. -
refresh — частота обновления кэшированных результатов. Значение по умолчанию:
1m - resolvers — список DNS-резолверов для переопределения системных резолверов.
- dial_timeout — таймаут для соединения с запросом.
-
dial_fallback_delay — время ожидания перед запуском соединения с быстрым отказом RFC 6555. Значение по умолчанию:
300ms
A/AAAA
Извлекает потоки из записей A/AAAA DNS.
dynamic a [<name> <port>] {
name <name>
port <port>
refresh <interval>
resolvers <ip...>
dial_timeout <duration>
dial_fallback_delay <duration>
versions ipv4|ipv6
}
- name — доменное имя для запроса.
- port — порт для использования в бэкенде.
-
refresh — частота обновления кэшированных результатов. Значение по умолчанию:
1m - resolvers — список DNS-резолверов для переопределения системных резолверов.
- dial_timeout — таймаут для соединения с запросом.
-
dial_fallback_delay — время ожидания перед запуском соединения с быстрым отказом RFC 6555. Значение по умолчанию:
300ms -
versions — список версий IP для разрешения. Значение по умолчанию:
ipv4 ipv6, соответствующие записям A и AAAA соответственно.
Многочисленные
Добавляет результаты нескольких модулей динамических потоков. Полезно, если нужно несколько источников потоков, например: основной кластер SRV, резервируемый вторичным кластером SRV.
dynamic multi {
<source> [...]
}
- <source> — имя модуля для динамических потоков, за которым следует его конфигурация. Можно указать несколько.
Балансировка нагрузки
Балансировка нагрузки обычно используется для распределения трафика между несколькими потоками. Включив повторные попытки, её также можно использовать с одним или несколькими потоками для удержания запросов до тех пор, пока не будет выбран здоровый поток (например, для ожидания и минимизации ошибок при перезапуске или переразвёртывании потока).
Это включено по умолчанию с политикой random. Повторные попытки отключены по умолчанию.
-
lb_policy — это имя политики балансировки нагрузки, а также любые опции. По умолчанию:
random.Для политик, включающих хэширование, используется алгоритм «наибольший случайный вес (HRW)» для обеспечения того, что клиент или запрос с тем же ключом хэша будут сопоставлены с тем же upstream, даже если список upstream изменится.
Некоторые политики поддерживают откат как опцию, если это указано, в этом случае они принимают блок с
fallback <policy>, который принимает другую политику балансировки нагрузки. Для этих политик по умолчанию используетсяrandom. Настройка отката позволяет использовать вторичную политику, если первичная не выбирает ни одной, что позволяет создавать мощные комбинации. Если необходимо, откаты можно вкладывать несколько раз.Например,
headerможет использоваться в качестве первичной политики, чтобы разработчики могли выбрать определенный upstream, а в качестве отката —firstдля всех остальных соединений для реализации failover по первичному/вторичному принципу.lb_policy header X-Upstream { fallback first }-
randomслучайным образом выбирает upstream -
random_choose <n>выбирает два или более upstream случайным образом, затем выбирает один с наименьшей нагрузкой (nобычно равно 2) -
firstвыбирает первый доступный upstream в порядке их определения в конфигурации, что позволяет реализовать failover по первичному/вторичному принципу; не забудьте включить проверки состояния вместе с этим, иначе failover не произойдет -
round_robinитеративно проходит по каждому upstream -
weighted_round_robin <weights...>итеративно проходит по каждому upstream, учитывая указанные веса. Количество аргументов веса должно соответствовать количеству настроенных upstream. Веса должны быть неотрицательными целыми числами. Например, при двух upstream и весах5 1первый upstream будет выбираться 5 раз подряд, прежде чем второй upstream будет выбран один раз, затем цикл повторяется. Если в качестве веса используется ноль, это отключит выбор upstream для новых запросов. -
least_connвыбирает upstream с наименьшим количеством текущих запросов; если у нескольких хостов наименьшее количество запросов, один из этих хостов выбирается случайным образом -
ip_hashсопоставляет удалённый IP-адрес (непосредственный peer) со sticky upstream -
client_ip_hashсопоставляет IP-адрес клиента со sticky upstream; это лучше всего сочетается сservers > trusted_proxiesглобальной опцией, которая включает реальный парсинг IP-адреса клиента, в противном случае он ведет себя так же, как иip_hash -
uri_hashсопоставляет URI запроса (путь и запрос) со sticky upstream -
query [key]сопоставляет запрос запроса со sticky upstream, хэшируя значение запроса; если указанный ключ отсутствует, используется политика отката для выбора upstream (randomпо умолчанию) -
header [field]сопоставляет заголовок запроса со sticky upstream, хэшируя значение заголовка; если указанное поле заголовка отсутствует, используется политика отката для выбора upstream (randomпо умолчанию) -
cookie [<name> [<secret>]]при первом запросе от клиента (когда нет cookie), используется политика отката для выбора upstream (randomпо умолчанию), и заголовокSet-Cookieдобавляется в ответ (имя cookie по умолчанию —lb, если не указано). Значение cookie — это адрес подключения upstream выбранного upstream, хэшированный с помощью HMAC-SHA256 (используя<secret>в качестве общего секрета, пустая строка, если не указано).При последующих запросах, где cookie присутствует, значение cookie будет сопоставлено с тем же upstream, если он доступен; если он недоступен или не найден, новый upstream выбирается с использованием политики отката, и cookie добавляется в ответ.
Если вы хотите использовать определённый upstream для отладки, вы можете захешировать адрес upstream с секретом и установить cookie в своём HTTP-клиенте (браузере или ином). Например, с PHP вы можете выполнить следующее для вычисления значения cookie, где
10.1.0.10:8080— адрес одного из ваших upstream, аsecret— ваш настроенный секрет.echo hash_hmac('sha256', '10.1.0.10:8080', 'secret'); // cdd96966817dd14a99f47ee17451464f29998da170814a16b483e4c1ff4c48cfВы можете установить cookie в своём браузере через консоль Javascript, например, для установки cookie с именем
lb:document.cookie = "lb=cdd96966817dd14a99f47ee17451464f29998da170814a16b483e4c1ff4c48cf";
-
-
lb_retries — количество попыток повторного выбора доступных бэкендов для каждого запроса, если следующий доступный хост недоступен. По умолчанию повторные попытки отключены (ноль).
Если также настроено
lb_try_duration, то повторные попытки могут завершиться раньше, если время истекло. Другими словами, время повторных попыток имеет приоритет над количеством повторных попыток. -
lb_try_duration — значение длительности, определяющее, как долго пытаться выбрать доступные бэкенды для каждого запроса, если следующий доступный хост недоступен. По умолчанию повторные попытки отключены (длительность равна нулю).
Клиенты будут ждать не более этого времени, пока балансировщик нагрузки пытается найти доступный хост upstream. Разумной отправной точкой может быть
5s, так как по умолчанию таймаут подключения транспортного протокола HTTP составляет3s, поэтому это позволит сделать хотя бы одну повторную попытку, если первый выбранный upstream недоступен; но не стесняйтесь экспериментировать, чтобы найти правильный баланс для вашего случая использования. -
lb_try_interval — значение длительности, определяющее, сколько времени ждать между выбором следующего хоста из пула. По умолчанию
250ms. Актуально только в случае неудачи запроса к хосту upstream. Имейте в виду, что установка этого значения на0при ненулевом значенииlb_try_durationможет привести к загрузке ЦП, если все бэкенды недоступны и задержка очень мала. -
lb_retry_match — ограничение повторных попыток для определенных запросов. Запрос должен соответствовать этому условию, чтобы повторно пытаться выполнить запрос, если подключение к upstream прошло успешно, но последующий обмен данными завершился неудачей. Если подключение к upstream завершилось неудачей, повторная попытка всегда разрешена. По умолчанию повторные попытки разрешены только для запросов
GET.Синтаксис этой опции такой же, как для названных соответствий запросов, но без
@name. Если вам нужен только один матчер, вы можете настроить его в одной строке. Для нескольких матчеров необходим блок.
Активные проверки состояния
Активные проверки состояния выполняют проверку состояния в фоновом режиме по таймеру. Для включения этого требуется health_uri или health_port.
-
health_uri — путь URI (и необязательный запрос) для активных проверок состояния.
-
health_upstream — ip:порт для использования в активных проверках состояния, если он отличается от upstream. Это следует использовать в сочетании с
health_headerи{http.reverse_proxy.active.target_upstream}. -
health_port — порт для использования в активных проверках состояния, если он отличается от порта upstream. Игнорируется, если используется
health_upstream. -
health_interval — значение длительности, определяющее, как часто выполнять активные проверки состояния. По умолчанию:
30s. -
health_passes — количество последовательных проверок состояния, необходимых для повторного обозначения бэкенда как здорового. По умолчанию:
1. -
health_fails — количество последовательных проверок состояния, необходимых для обозначения бэкенда как нездорового. По умолчанию:
1. -
health_timeout — значение длительности, определяющее, как долго ждать ответа, прежде чем обозначить бэкенд как нерабочий. По умолчанию:
5s. -
health_status — код HTTP-статуса, ожидаемый от здорового бэкенда. Может быть трёхзначным кодом статуса или классом кода статуса, заканчивающимся на
xx. Например:200(по умолчанию) или2xx. -
health_body — подстрока или регулярное выражение для сопоставления с телом ответа активной проверки состояния. Если бэкенд не возвращает совпадающее тело, он будет помечен как нерабочий.
-
health_follow_redirects — заставит проверку состояния переходить по редиректам, предоставленным upstream. По умолчанию ответ с редиректом приведёт к тому, что проверка состояния будет считаться неудачной.
-
health_headers — позволяет задавать заголовки для запросов активной проверки состояния. Это полезно, если вам нужно изменить заголовок
Hostили если вам нужно предоставить аутентификацию вашему бэкенду в рамках проверок состояния.
Пассивные проверки состояния
Пассивные проверки состояния происходят совместно с фактическими запросами, перенаправляемыми прокси-сервером. Для включения этого требуется fail_duration.
-
fail_duration — значение длительности, определяющее, как долго запоминать неудачный запрос. Длительность >
0включает пассивные проверки состояния; по умолчанию0(выключено). Разумной отправной точкой может быть30s, чтобы сбалансировать частоту ошибок и отзывчивость при возвращении нерабочего upstream в активное состояние; но не стесняйтесь экспериментировать, чтобы найти правильный баланс для вашего случая использования. -
max_fails — максимальное количество неудачных запросов в течение
fail_duration, которое необходимо, чтобы считать бэкенд нерабочим; должно быть >=1; по умолчанию1. -
unhealthy_status — считает запрос неудачным, если ответ возвращается с одним из этих кодов статуса. Может быть трёхзначным кодом статуса или классом кода статуса, заканчивающимся на
xx, например:404или5xx. -
unhealthy_latency — значение длительности, которое считает запрос неудачным, если на получение ответа требуется это время.
-
unhealthy_request_count — допустимое количество одновременных запросов к бэкенду, прежде чем отметить его как нерабочий. Другими словами, если определённый бэкенд в настоящее время обрабатывает это количество запросов, то он считается «перегруженным», и вместо него будут предпочтительны другие бэкенды.
Это должно быть достаточно большим числом; настройка этого означает, что прокси-сервер будет иметь ограничение
unhealthy_request_count × upstreams_countодновременных запросов, и все запросы после этого момента приведут к ошибке из-за отсутствия доступных upstream.
События
Когда upstream переходит из состояния «здоровый» в «нездоровый» или наоборот, генерируется событие. Эти события могут быть использованы для запуска других действий, таких как отправка уведомления или запись сообщения. События следующие:
-
healthyизлучается, когда восходящий поток отмечается как здоровый, когда он был ранее нездоровым -
unhealthyизлучается, когда восходящий поток отмечается как нездоровый, когда он был ранее здоровым
В обоих случаях, host включается в качестве метаданных в событии, чтобы идентифицировать восходящий поток, состояние которого изменилось. Он может использоваться в качестве заполнителя с {event.data.host} с обработчиком событий exec, например.
Потоковая передача
По умолчанию прокси частично буферизует ответ для повышения эффективности передачи данных.
Прокси также поддерживает подключения WebSocket, выполняя запрос на обновление HTTP, а затем переключая соединение на двунаправленный туннель.
-
flush_interval — это значение длительности, которое регулирует частоту сброса буфера ответа прокси-сервером клиенту. По умолчанию периодического сброса не происходит. Отрицательное значение (обычно -1) означает «режим низкой задержки», который полностью отключает буферизацию ответа и выполняет сброс немедленно после каждого записи клиенту, а также не отменяет запрос к бэкенду, даже если клиент отсоединится слишком рано. Этот параметр игнорируется, и ответы сбрасываются немедленно клиенту, если выполняется одно из следующих условий:
Content-Type: text/event-streamContent-Lengthнеизвестен- HTTP/2 с обеих сторон прокси,
Content-Lengthнеизвестен, иAccept-Encodingне задан или равен "identity"
-
request_buffers заставит прокси читать до
<size>байт из тела запроса в буфер перед отправкой в восходящий поток. Это очень неэффективно и следует применять только в том случае, если восходящий поток требует чтения тел запросов без задержки (что должна исправить сама приложение восходящего потока). Принимает все форматы размеров, поддерживаемые go-humanize. -
response_buffers заставит прокси читать до
<size>байт из тела ответа в буфер перед возвратом клиенту. Следует избегать этого для повышения производительности, но это может быть полезно, если бэкенд имеет более жёсткие ограничения по памяти. Принимает все форматы размеров, поддерживаемые go-humanize. -
stream_timeout — это значение длительности, по истечении которого потоковые запросы, такие как WebSocket, будут насильственно закрыты в конце тайм-аута. Это фактически отменяет соединения, если они остаются открытыми слишком долго. Хорошим начальным значением может быть
24hдля удаления соединений старше суток. По умолчанию тайм-аут отсутствует. -
stream_close_delay — это значение длительности, которое задерживает насильственное закрытие потоковых запросов, таких как WebSocket, при разгрузке конфигурации. Вместо этого поток останется открытым до завершения задержки. Другими словами, включение этого параметра предотвращает немедленное закрытие потоков при перезагрузке конфигурации Caddy. Это может быть полезно для предотвращения «наплыва» повторных подключений клиентов, подключения которых были закрыты при закрытии предыдущей конфигурации. Хорошим начальным значением может быть что-то вроде
5m, чтобы дать пользователям 5 минут на то, чтобы естественным образом покинуть страницу после перезагрузки конфигурации. По умолчанию задержка отсутствует.
Заголовки
Прокси может манипулировать заголовками между собой и бэкендом:
-
header_up устанавливает, добавляет (с префиксом
+), удаляет (с префиксом-) или выполняет замену (используя два аргумента, поиск и замену) в заголовке запроса, идущем в восходящий поток к бэкенду. -
header_down устанавливает, добавляет (с префиксом
+), удаляет (с префиксом-) или выполняет замену (используя два аргумента, поиск и замену) в заголовке ответа, идущем вниз по потоку от бэкенда.
Например, чтобы установить заголовок запроса, перезаписывая любые существующие значения:
header_up Some-Header "the value"
Чтобы добавить заголовок ответа; обратите внимание, что для поля заголовка может быть несколько значений:
header_down +Some-Header "first value"
header_down +Some-Header "second value"
Чтобы удалить заголовок запроса, предотвращая его передачу бэкенду:
header_up -Some-Header
Чтобы удалить все соответствующие заголовки запроса, используя совпадение по суффиксу:
header_up -Some-*
Чтобы удалить все заголовки запроса, чтобы можно было индивидуально добавить нужные (не рекомендуется):
header_up -*
Чтобы выполнить замену регулярного выражения в заголовке запроса:
header_up Some-Header "^prefix-([A-Za-z0-9]*)$" "replaced-$1-suffix"
Используемый язык регулярных выражений — RE2, включённый в Go. См. справочник по синтаксису RE2 и обзор синтаксиса регулярных выражений Go. Строка замены расширяется, что позволяет использовать захваченные значения, например, $1 — это первая группа захвата.
Значения по умолчанию
По умолчанию Caddy передает входящие заголовки — включая Host — бэкенду без изменений, за исключением трёх случаев:
- Он устанавливает или дополняет поле заголовка
X-Forwarded-For. - Он устанавливает поле заголовка
X-Forwarded-Proto. - Он устанавливает поле заголовка
X-Forwarded-Host.
Для этих X-Forwarded-* заголовков прокси по умолчанию игнорирует их значения из входящих запросов, чтобы предотвратить подделку.
Если Caddy не является первым сервером, к которому подключаются ваши клиенты (например, когда перед Caddy находится CDN), вы можете настроить trusted_proxies с перечнем диапазонов IP-адресов (CIDR), из которых входящие запросы считаются надёжными для передачи корректных значений этих заголовков.
Настоятельно рекомендуется настроить это через глобальный параметр servers > trusted_proxies вместо настройки в прокси, чтобы это применялось ко всем обработчикам прокси на вашем сервере. Это также позволит парсить IP-адреса клиентов.
Кроме того, при использовании транспорта http заголовок Accept-Encoding: gzip будет установлен, если он отсутствует в запросе от клиента. Это позволяет восходящему потоку предоставлять сжатый контент, если он поддерживается. Это поведение можно отключить с помощью compression off в транспорте.
HTTPS
Поскольку (большинство) заголовков сохраняют своё первоначальное значение при проксировании, часто необходимо переопределить заголовок Host на адрес конфигурированного восходящего потока при проксировании на HTTPS, чтобы заголовок Host соответствовал значению ServerName TLS:
reverse_proxy https://example.com {
header_up Host {upstream_hostport}
}
Заголовок X-Forwarded-Host всё ещё передаётся по умолчанию, поэтому восходящий поток может использовать его, если ему нужно знать первоначальное значение заголовка Host.
Перенаправления
По умолчанию Caddy выполняет запрос к восходящему потоку с тем же методом HTTP и URI, что и входящий запрос, если не было выполнено перенаправление в цепочке обработки middleware перед достижением reverse_proxy.
Перед проксированием запрос клонируется. Это гарантирует, что любые изменения, внесённые в запрос во время обработки, не попадут в другие обработчики. Это полезно в ситуациях, когда обработка должна продолжаться после прокси.
В дополнение к манипуляциям с заголовками, метод и URI запроса могут быть изменены перед отправкой в восходящий поток:
-
method изменяет метод HTTP клонированного запроса. Если метод изменён на
GETилиHEAD, то тело входящего запроса не будет отправлено в восходящий поток этим обработчиком. Это полезно, если вы хотите разрешить другому обработчику обработать тело запроса. -
rewrite изменяет URI (путь и запрос) клонированного запроса. Это аналогично
rewriteдирективе, за исключением того, что перенаправление не сохраняется после обработки этим обработчиком.
Эти перенаправления часто полезны для схемы «предварительная проверка запросов», где запрос отправляется на другой сервер, чтобы помочь принять решение о том, как продолжить обработку текущего запроса.
Например, запрос может быть отправлен на шлюз аутентификации, чтобы определить, был ли запрос от аутентифицированного пользователя (например, запрос содержит куки сессии) и должен ли он продолжить, или вместо этого перенаправить на страницу входа. Для этой схемы Caddy предоставляет сокращённую директиву forward_auth, чтобы пропустить большую часть настроек конфигурации.
Транспортные средства
Транспортный механизм прокси Caddy настраивается:
-
transport определяет способ взаимодействия с бэкендом. Значение по умолчанию —
http.
Транспорт http
transport http {
read_buffer <size>
write_buffer <size>
max_response_header <size>
proxy_protocol v1|v2
dial_timeout <duration>
dial_fallback_delay <duration>
response_header_timeout <duration>
expect_continue_timeout <duration>
resolvers <ip...>
tls
tls_client_auth <automate_name> | <cert_file> <key_file>
tls_insecure_skip_verify
tls_curves <curves...>
tls_timeout <duration>
tls_trust_pool <module>
tls_server_name <server_name>
tls_renegotiation <level>
tls_except_ports <ports...>
keepalive [off|<duration>]
keepalive_interval <interval>
keepalive_idle_conns <max_count>
keepalive_idle_conns_per_host <count>
versions <versions...>
compression off
max_conns_per_host <count>
forward_proxy_url <url>
}
-
read_buffer — размер буфера чтения в байтах. Принимает все форматы, поддерживаемые go-humanize. По умолчанию:
4KiB. -
write_buffer — размер буфера записи в байтах. Принимает все форматы, поддерживаемые go-humanize. По умолчанию:
4KiB. -
max_response_header — максимальное количество байтов для чтения из заголовков ответа. Принимает все форматы, поддерживаемые go-humanize. По умолчанию:
10MiB. -
proxy_protocol — включает протокол PROXY (распространённый благодаря HAProxy) при соединении с сервером, добавляя данные реального IP-адреса клиента. Лучше всего использовать вместе с
servers > trusted_proxiesглобальным параметром, если Caddy находится за другим прокси. Поддерживаются версииv1иv2. Это следует использовать только в том случае, если вы уверены, что сервер может обрабатывать PROXY-протокол. По умолчанию отключено. -
dial_timeout — максимальное время ожидания подключения к сокету сервера. По умолчанию:
3s. -
dial_fallback_delay — максимальное время ожидания перед созданием соединения RFC 6555 Fast Fallback. Отрицательное значение отключает это. По умолчанию:
300ms. -
response_header_timeout — максимальное время ожидания чтения заголовков ответа от сервера. По умолчанию: без ограничения.
-
expect_continue_timeout — максимальное время ожидания первых заголовков ответа сервера после полной отправки заголовков запроса, если запрос содержит заголовок
Expect: 100-continue. По умолчанию: без ограничения. -
read_timeout — максимальное время ожидания следующего чтения от сервера. По умолчанию: без ограничения.
-
write_timeout — максимальное время ожидания следующей записи на сервер. По умолчанию: без ограничения.
-
resolvers — список DNS-серверов для переопределения системных.
-
tls — использует HTTPS с сервером. Будет включено автоматически, если вы указали серверы с
https://схемой или портом:443, или если настроен любой из параметровtls_*. -
tls_client_auth — включает TLS-аутентификацию клиента одним из двух способов: (1) указанием доменного имени, для которого Caddy должен получить сертификат и поддерживать его обновление, или (2) указанием файла сертификата и ключа для представления при TLS-аутентификации клиента с сервером.
-
tls_insecure_skip_verify — отключает проверку TLS-рукопожатия, делая подключение небезопасным и уязвимым к атакам «человек посередине». Не использовать в продакшене.
-
tls_curves — список эллиптических кривых для поддержки соединения с сервером. Значения по умолчанию Caddy современные и безопасные, поэтому вам следует настраивать этот параметр только в случае специальных требований.
-
tls_timeout — максимальное время ожидания завершения TLS-рукопожатия. По умолчанию: без ограничения.
-
tls_trust_pool — настраивает источник доверенных центров сертификации аналогично
trust_poolподнаправлению, описанному в документации поtlsпараметру. Список доступных источников пула доверия в стандартной установке Caddy доступен здесь. -
tls_server_name — устанавливает имя сервера, используемое при проверке сертификата, полученного в рамках TLS-рукопожатия. По умолчанию используется имя хоста из адреса сервера.
Вам нужно переопределить его только в том случае, если адрес сервера не соответствует сертификату, который сервер, скорее всего, использует. Например, если адрес сервера — IP-адрес, вам нужно настроить его на имя хоста, обслуживаемое сервером.
Можно использовать заполнитель запроса, в этом случае для каждого запроса будет использоваться клон конфигурации HTTP-транспорта, что может привести к снижению производительности.
-
tls_renegotiation — устанавливает уровень TLS-повторного согласования. TLS-повторное согласование — это действие по выполнению последующих рукопожатий после первого. Уровень может быть одним из:
-
never(по умолчанию) отключает повторное согласование. -
onceпозволяет удалённому серверу запросить повторное согласование один раз на подключение. -
freelyпозволяет удалённому серверу многократно запрашивать повторное согласование.
-
-
tls_except_ports — при включённом TLS, если целевой сервер использует один из заданных портов, TLS будет отключён для этих подключений. Это может быть полезно при настройке динамических серверов, где некоторые сервера ожидают HTTP-запросы, а другие — HTTPS.
-
keepalive — либо
off, либо значение длительности, указывающее, как долго следует поддерживать открытыми подключения (таймаут). По умолчанию:2m. -
keepalive_interval — длительность между проверками состояния. По умолчанию:
30s. -
keepalive_idle_conns — определяет максимальное количество подключений, которые необходимо поддерживать в режиме ожидания. По умолчанию: без ограничения.
-
keepalive_idle_conns_per_host — если ненулевое, контролирует максимальное количество подключений в режиме ожидания (keep-alive) на хост. По умолчанию:
32. -
versions — позволяет настроить поддерживаемые версии HTTP.
Допустимые значения:
1.1,2,h2c,3.По умолчанию:
1.1 2, или если схема сервера —h2c://, тогда значение по умолчанию —h2c 2.h2cвключает соединения HTTP/2 без шифрования с сервером. Это нестандартная функция, которая не использует стандартный Go HTTP-транспорт, поэтому она исключает другие функции.3включает соединения HTTP/3 с сервером. ⚠️ Эта функция является экспериментальной и может быть изменена. -
compression — может использоваться для отключения сжатия на сервере, задав значение
off. -
max_conns_per_host — необязательно ограничивает общее количество подключений на хост, включая подключения в состояниях установления соединения, активные и в режиме ожидания. По умолчанию: без ограничения.
-
forward_proxy_url — указывает URL сервера, который HTTP-транспорт будет использовать для проксирования запросов к серверу. По умолчанию Caddy учитывает прокси, настроенные через переменные окружения, как в Go stdlib, например,
HTTP_PROXY. При указании значения для этого параметра запросы будут проходить через обратный прокси в следующем порядке:- Клиент (пользователи) 🡒
reverse_proxy🡒forward_proxy_url🡒 сервер
- Клиент (пользователи) 🡒
Транспорт fastcgi
transport fastcgi {
root <path>
split <at>
env <key> <value>
resolve_root_symlink
dial_timeout <duration>
read_timeout <duration>
write_timeout <duration>
capture_stderr
}
-
root — корень сайта. По умолчанию:
{http.vars.root}или текущий каталог. -
split — место разделения пути для получения PATH_INFO в конце URI.
-
env — устанавливает дополнительную переменную окружения со значением. Можно указывать несколько раз для нескольких переменных окружения.
-
resolve_root_symlink — включает разрешение символьной ссылки для каталога
rootдо его реального значения путём оценки символьной ссылки, если она существует. -
dial_timeout — время ожидания подключения к сокету сервера. Принимает значения длительности. По умолчанию:
3s. -
read_timeout — время ожидания чтения с сервера FastCGI. Принимает значения длительности. По умолчанию: без таймаута.
-
write_timeout — время ожидания отправки на сервер FastCGI. Принимает значения длительности. По умолчанию: без таймаута.
-
capture_stderr — включает захват и логирование любых сообщений, отправленных сервером FastCGI в
stderr. Логирование выполняется на уровнеWARNпо умолчанию. Если ответ имеет статус4xxили5xx, то будет использован уровеньERROR. По умолчаниюstderrигнорируется.
Перехват ответов
Обратный прокси можно настроить для перехвата ответов от сервера. Для этого можно определить обработчики ответов (аналогично синтаксису для обработчиков запросов), и первый соответствующий handle_response маршрут будет вызван.
Когда вызывается обработчик ответа, ответ от сервера не отправляется клиенту, а вместо этого выполняется настроенный handle_response маршрут, и этот маршрут отвечает за отправку ответа. Если маршрут не отправляет ответ, обработка запроса продолжится с любыми обработчиками, которые упорядочены после этого reverse_proxy.
-
@name — имя обработчика ответа. Пока каждый обработчик ответа имеет уникальное имя, можно определить несколько обработчиков. Ответ может быть сопоставлен по коду состояния и наличию или значению заголовка ответа.
-
replace_status — просто изменяет код состояния ответа при совпадении с заданным обработчиком.
-
handle_response — определяет маршрут для выполнения при совпадении с заданным обработчиком (или, если обработчик не указан, для всех ответов). Будет применено первое соответствующее правило. Внутри блока
handle_responseможно использовать любые другие параметры.
Кроме того, внутри handle_response могут использоваться два специальных обработчика:
-
copy_response копирует тело ответа, полученное от бэкенда, обратно клиенту. Позволяет опционально изменить код состояния ответа при этом. Данная директива упорядочена до
respond. -
copy_response_headers копирует заголовки ответа из бэкенда клиенту, опционально включая ИЛИ исключая список полей заголовков (нельзя указать оба
includeиexclude). Данная директива упорядочена послеheader.
Три плейсхолдера будут доступны в пределах handle_response маршрутов:
-
{rp.status_code}Код состояния ответа от бэкенда. -
{rp.status_text}Текст состояния ответа от бэкенда. -
{rp.header.*}Заголовки ответа от бэкенда.
Примеры
Обратный прокси всех запросов к локальному бэкенду:
example.com {
reverse_proxy localhost:9005
}
Распределение нагрузки всех запросов между 3 бэкендами:
example.com {
reverse_proxy node1:80 node2:80 node3:80
}
То же, но только для запросов в /api, и с сохранением соединения с помощью cookie политики:
example.com {
reverse_proxy /api/* node1:80 node2:80 node3:80 {
lb_policy cookie api_sticky
}
}
Использование активных проверок работоспособности для определения работоспособности бэкендов и включение повторных попыток при сбоях соединений, удерживая запрос до тех пор, пока не будет найден работоспособный бэкенд:
example.com {
reverse_proxy node1:80 node2:80 node3:80 {
health_uri /healthz
lb_try_duration 5s
}
}
Настройка некоторых параметров транспорта:
example.com {
reverse_proxy localhost:8080 {
transport http {
dial_timeout 2s
response_header_timeout 30s
}
}
}
Обратный прокси к HTTPS upstream:
example.com {
reverse_proxy https://example.com {
header_up Host {upstream_hostport}
}
}
Обратный прокси к HTTPS upstream, но ⚠️ отключить проверку TLS. Это НЕ РЕКОМЕНДУЕТСЯ, так как это отключает все меры безопасности, предлагаемые HTTPS; проксирование по HTTP в частных сетях предпочтительнее, если это возможно, потому что это избегает ложного чувства безопасности:
example.com {
reverse_proxy 10.0.0.1:443 {
transport http {
tls_insecure_skip_verify
}
}
}
Вместо этого можно установить доверие к upstream, явно доверяя сертификату upstream, и (необязательно) устанавливая TLS-SNI для соответствия имени хоста в сертификате upstream:
example.com {
reverse_proxy 10.0.0.1:443 {
transport http {
tls_trusted_ca_certs /path/to/cert.pem
tls_server_name app.example.com
}
}
}
Удалить префикс пути перед проксированием; но будьте осторожны из-за проблемы подкаталога:
example.com {
handle_path /prefix/* {
reverse_proxy localhost:9000
}
}
Заменить префикс пути перед проксированием, используя rewrite:
example.com {
handle_path /old-prefix/* {
rewrite * /new-prefix{path}
reverse_proxy localhost:9000
}
}
X-Accel-Redirect поддержка, т.е. предоставление статических файлов по запросу, путем перехвата ответа:
example.com {
reverse_proxy localhost:8080 {
@accel header X-Accel-Redirect *
handle_response @accel {
root * /path/to/private/files
rewrite * {rp.header.X-Accel-Redirect}
method * GET
file_server
}
}
}
Пользовательская страница ошибки для ошибок от upstream, путем перехвата ответов об ошибках по коду состояния:
example.com {
reverse_proxy localhost:8080 {
@error status 500 503
handle_response @error {
root * /path/to/error/pages
rewrite * /{rp.status_code}.html
file_server
}
}
}
Получение бэкендов динамически из A/AAAA записи запросов DNS:
example.com {
reverse_proxy {
dynamic a example.com 9000
}
}
Получение бэкендов динамически из SRV записи запросов DNS:
example.com {
reverse_proxy {
dynamic srv _api._tcp.example.com
}
}
Использование активных проверок работоспособности и health_upstream может быть полезно при создании промежуточной службы для более тщательной проверки работоспособности. {http.reverse_proxy.active.target_upstream} затем может быть использован в качестве заголовка для предоставления исходного upstream службе проверки работоспособности.
example.com {
reverse_proxy node1:80 node2:80 node3:80 {
health_uri /health
health_upstream 127.0.0.1:53336
health_headers {
Full-Upstream {http.reverse_proxy.active.target_upstream}
}
}
}
© 2015-2025 Matthew Holt and The Caddy Authors
Licensed under the Apache License 2.0.
Caddy is a registered trademark of Stack Holdings GmbH.
https://caddyserver.com/docs/caddyfile/directives/reverse_proxy