@midia21

Как разрешить вызов api контроллера, только одному серверу по ip (который отправляет вебхук)?

Пишу небольшой проект на golang. В этом проекте осуществляется подписка на вебхук, который при определенном событии отправляет запрос на url, указанный при регистрации хука. Собственно, вопрос по безопасности. Как сделать так, чтобы только сервер, отправляющий вебхук, мог получить доступ к моему контроллеру, обрабатывающему вебхук. Ведь потенциально, если об этом не подумать, любой сможет через postman отправить myserver/webhook-handler и внедрить левые данные.

В мануалах гитхаба (просто наткнулся на описание работы с их вебхуками) описан хороший способ решений проблемы: при регистрации вебхука отправлять секретный ключ, который будет приходить в мой контроллер с полезной нагрузкой при каждом срабатывании хука. Этот ключ будет храниться также и на моем серваке, и дальше можно просто сверить пришедший и имеющийся.
https://docs.github.com/en/developers/webhooks-and...

Однако есть одна проблема - api с которым работаю не поддерживает секретные ключи. Кто то знает еще способы решения данной проблемы? Заранее спасибо.

P.S. Также в манулах гитхаба описан другой вариант - давать доступ к обработчику только определенным IP адресам. Но понятия не имею как это реализовать, чтобы избежать подделывания адресов. Это настраивается на стороне вебсервера (например апача) или непосредственно в коде? Буду также рад примерам на любых языках.
  • Вопрос задан
  • 80 просмотров
Решения вопроса 1
EvgenyMamonov
@EvgenyMamonov Куратор тега Go
Senior software developer, system architect
Чаще всего, в таких случаях, используют секретный ключ, который передают или в параметрах запроса (так лучше не делать, т.к. секретный ключ будет виден в логах промежуточных прокси и сервера) или в HTTP заголовке (этот вариант безопаснее, чем передача в параметрах запроса).

Реже используют вариант с цифровой подписью запроса. Этот вариант ощутимо безопаснее, чем передавать секретный ключ в открытом виде. При таком варианте вы не только знаете о том, что запрос отправил нужный вам сервер, но и о том, что запрос не был изменён никем (например прокси сервером).

Но оба эти варианта требуют доработки со стороны отправляющего запрос сервера.
Как я понимаю для вас этот вариант не доступен.

В принципе вариант защиты по IP адресу вполне нормальный.
Самый простой способ - настроить firewall, т.е. закрыть доступ всем к вашему сервису и открыть только для IP сервера, который делает запросы.

Если вариант с firewall не подходит - можно обеспечивать защиту на стороне Go.
IP можно получать из запроса HTTP https://pkg.go.dev/net/http#Request

Вот готовый пример
package main

import (
    "fmt"
    "log"
    "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Your IP is %s", r.RemoteAddr)
}

func main() {
    http.HandleFunc("/", handler)
    log.Fatal(http.ListenAndServe(":8080", nil))
}

Иногда (зависит от настроек веб сервера) реальный IP может приходить в HTTP заголовках запроса
ip := r.Header.Get("X-Forwarded-For")
// или
ip := r.Header.Get("X-Real-IP")
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы