Немного истории, реализация php, perl и банальная реализация на Golang.
Интересно? Добро пожаловать в подкат...


Как вы прекрасно знаете, с марта 2024 года, РКН начал накладывать ограничение на публикации в СМИ о способах обхода блокировок.

Сообщаем вам, что на ваш материал на сайте Habr.com было наложено ограничение доступа для пользователей из определённой страны:
Регион: RU
Дата: 01.03.2024
Причина: RU / 149-ФЗ: 15.1.8
Ведомство: RU / Роскомнадзор

Следовательно, данный материал не доступен при обращении с IP адреса, который принадлежит country: RU

Посмотреть можно например тут

Как же можно поменять IP адрес запроса?

Конечно, сейчас каждое домохозяйство как минимум раз в день обсуждает VPN, давайте вспомним, как это было во времена, когда интернет не был безлимитным и активно строились первые районные локальные сети.

Во времена Web 1.0 вовсю существовали всем известные сетевые протоколы и способы проксирования, например

  • HTTP(S)

  • SOCKS Прокси (SOCKS4, SOCKS5)

Однако т.к. самый популярный язык того времени был PHP, то и очень много проектов для проксирования запросов было написано именно на нем.
Несколько примеров: miniProxy и пожалуй самая известная - SF PHProxy (GH - PHProxy , emersion)

Конечно, нельзя не вспомнить о CGIProxy.

Из сервисов, например есть CroxyProxy, которые позволяют бесплатно привязать свой домен и создать свой сервис анонимизации. (Такая же технология используется и на проекте reflect4).

Если говорить про другие способы - можно выделить например Tor, но статей на хабре достаточно, те, кому интересно, прекрасно сами найдут в поиске.

Мне нравится язык Go, давайте напишем на нем программу, которая покажет нам другой Хабр. Фактически сделаем прокси хабр, чтобы запросы шли через IP адрес сервера, где будет запущено приложение, тем самым будем смотреть на сайт, как будто наш IP адрес - из другой страны.
Как арендовать сервер в другой стране можно поискать в яндексе или посмотреть на другую мою статью, ссылка будет в конце.

Банальная GO реализация

Для начала продумаем простую схему реализации. Самую банальную, чтобы была понятна концепция.
Нам нужно принять REST (Representational State Transfer) запрос, повторить его от имени сервера, полученный результат поменять, чтобы все ссылки и указания изменились с первоначального адреса на наш текущий, и, наконец, вернуть клиенту результат.

Мы берем сервис, который принимает запросы (в нашем случае :80) и перенаправляет их на habr.com:443

const (
	urlOld  = "habr.com"
	urlNew  = "habr-test.yandex.tel"
	portRun = "80"
)

В качестве инструментов будем использовать стандартные библиотеки и для упрощения возьмем еще gin

import (
	"io"
	"net/http"
	"net/url"
	"strings"

	"github.com/gin-gonic/gin"
)

В функции main мы создадим наш веб сервер, который будет слушать все запросы, и будем прокидывать весь наш полученный путь в remoteUrl в fetchRemoteContent и полученный результат вернем клиенту.

func main() {
	r := gin.Default()
	r.Any("/*proxyPath", func(c *gin.Context) {
		proxyPath := c.Param("proxyPath")

		remoteUrl := "https://" + urlOld + proxyPath
		remote, err := url.Parse(remoteUrl)
		if err != nil {
			c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid URL"})
			return
		}

		// Делаем запрос к удаленному серверу для получения содержимого
		content, contentType, headers, err := fetchRemoteContent(remote.String(), c.Request)
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch remote content"})
			return
		}

		// прокидываем заголовки ответа удаленного сервера
		for key, values := range headers {
			for _, value := range values {
				c.Writer.Header().Add(key, value)
			}
		}

		c.Data(http.StatusOK, contentType, content)
	})

	r.Run(":" + portRun)
}

А что будем делать в клиенте? Собственно все тоже самое, что пришло к нам:

  • Создадим Request с параметрами, которые пришли к нам

  • Пробросим заголовки

  • Сделаем запрос

  • Вычитаем ответ

  • Поменяем текстовое содержимое

  • Если был редирект, корректно его отработаем

  • И вернем результат из функции

func fetchRemoteContent(remoteUrl string, originalRequest *http.Request) ([]byte, string, http.Header, error) {
	client := &http.Client{}

	req, err := http.NewRequest(originalRequest.Method, remoteUrl, originalRequest.Body)
	if err != nil {
		return nil, "", nil, err
	}

	for key, values := range originalRequest.Header {
		for _, value := range values {
			req.Header.Add(key, value)
		}
	}

	resp, err := client.Do(req)
	if err != nil {
		return nil, "", nil, err
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, "", nil, err
	}

	contentType := resp.Header.Get("Content-Type")
	if isTextContent(contentType) {
		body = []byte(strings.ReplaceAll(string(body), urlOld, urlNew))
	}

	if location := resp.Header.Get("Location"); location != "" {
		if strings.HasPrefix(location, "https://"+urlOld) {
			resp.Header.Set("Location", strings.Replace(location, urlOld, urlNew, 1))
		}
	}

	resp.Header.Del("Content-Length")

	return body, contentType, resp.Header, nil
}

И чтобы не засорять код, вынесем обработку типов контента, где будем менять содержимое

func isTextContent(contentType string) bool {
	textTypes := []string{
		"text/html",
		"application/javascript",
		"application/json",
		"text/plain",
		"application/xml",
		"text/css",
		"application/xhtml+xml",
	}

	for _, t := range textTypes {
		if strings.Contains(contentType, t) {
			return true
		}
	}
	return false
}

Итого, рабочий прототип можно посмотреть тут = https://habr-test.yandex.tel/ru/articles/790828/

И вот наш, уже другой хабр

Базовый функционал работает. В тч SSL
Базовый функционал работает. В тч SSL

И зачем нам это?

Но это все было в попытке объяснить, какая потенциально неограниченная черная дыра рунета нас может ожидать в ближайшее будущее.

Ведь уже сейчас происходит замедление ютуба, блокировка сетевых протоколов, белые листы корпоративных VPNов и сервисов. Что приводит к еще большему снижению общей защиты и пропуску всех предупреждений обычными пользователями.

Вот только самые популярные виды мошенничества, количество которых увеличивается каждый день.

  1. Увеличение количества фишинга
    Например, вы же обратили внимание, что любой человек может купить домен второго уровня yandex.{{какая нибудь из современных зон}} , разместить почту на Яндекс360, разместить сервер на яндексОблако и отправлять точечно фишинговые письма от имени Яндекс. Я уверен, половина специалистов ИБ не смогут отличить это от фишинга, не говоря уже об обычных пользователях ПК.

  2. Атака посредника или Man-in-the-Middle -> почитать тут

  3. Телефонные мошенники и другой вид старого "развода", используя просто новые инфоПоводы

Запреты никогда не помогают, а только оттягивают время наступления проблемы.
Интересно обсудить это вместе в комментариях.

Комментарии (9)


  1. lair
    28.07.2024 19:46
    +8

    Но это все было в попытке объяснить, какая потенциально неограниченная черная дыра рунета нас может ожидать в ближайшее будущее.

    Я, извините, в вашем объяснении не понял ровным счетом ничего.


  1. baldr
    28.07.2024 19:46

    Мда, действительно, что-то всё в кучу и непонятен посыл статьи.

    Зачем что-то писать на go, perl (?) и php (??), если можно взять, например, nginx или, прости хоспади, squid и просто поднять уже готовый прокси?

    Например, вы же обратили внимание, что любой человек может купить домен второго уровня yandex.{{какая нибудь из современных зон}} , разместить почту на Яндекс360, разместить сервер на яндексОблако и отправлять точечно фишинговые письма от имени Яндекс.

    Так можно и не яндекс. Давайте возьмем google.tel или gmail.tel? В общем-то, последние лет 20 с лишним фишинг так и работает - при чём тут подмена IP и роскомнадзор? Не просто так появились SPF, DKIM, DMARC и другие сложные слова.


    1. YungTrappa
      28.07.2024 19:46

      Пока одни блокируют, запрещают и в целом низвергают интернет в бездну безумия и киберопасностей – другие обходят блокировки, обучают других, объясняют методы запуска прокси на инженерном калькуляторе.

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

      Я так вижу.


      1. RichardMerlock
        28.07.2024 19:46
        +3

        По большому счету, если всё время жить в комфортной среде, с максимумом удобств и минимумом ответственности, то люди начинают деградировать. Время перемен закаляет, делает из потребителя Человека!


        1. Radisto
          28.07.2024 19:46

          Наверное есть предел, потому что люди из Либерии или Пенджаба явно более закалены, чем из нью-йорка или Хьюстона, но деградирующим называют чаще всего именно их


          1. baldr
            28.07.2024 19:46

            А кто называет, простите?


          1. RichardMerlock
            28.07.2024 19:46

            Имеют ввиду государственный строй и экономику. Люди там скорее всего житейски подкованные.


  1. Grogcm20
    28.07.2024 19:46
    +2

    "какая потенциально неограниченная черная дыра рунета нас может ожидать в ближайшее будущее"

    Началось это не сейчас, видно вы сами этого хотели, и планомерно к этому шли. Думали приспособиться, во всех решениях побеждал конформизм, а подойдя к краю пора уже определиться. Но пока еще не готовы, статьи стали более "удобные", украткой пытаться пронести смысл, скулите, не помогает ..., это ничего не поменяет. Время требует радикальных решений.


  1. alexklklkl
    28.07.2024 19:46

    Автору благодарность, да существуют готовые решения, но когда делается "на коленке" - быстрее приходит понимание, как работают эти готовые решения.