У меня, как и у многих посетителей Хабра есть raspberry pi. А ещё, почти честные сто мегабит от провайдера домашнего интернета. Идея о маленьком домашнем сервере от такой комбинации появляется сама по себе. Но сервер он ведь на то и сервер, чтобы работал независимо от факта нахождения пользователя в физической доступности. В связи с этим, возникает вопрос, как подключаться к такому серверу удалённо? Обычно провайдеры домашнего интернета прячут своих пользователей за NAT, так как IPv4 на всех не напасёшься. Мой провайдер исключением не является. Внешний статический IP он так же не предоставляет (по крайней мере, такой услуги в ЛК я не нашёл), да и совершенно ни к чему выставлять шлюз в локальную домашнюю сеть во внешний интернет. Shodan, ботнеты, сканеры и краулеры никто не отменял. Раньше для подобной задачи решение было очевидным – виртуальная частная сеть. Однако сейчас, с учётом нарушения сетевого коннекта по определённым протоколам, хочется иметь как минимум резервный удалённый канал связи. Да, нарушение коннекта по привычным для данной задачи протоколам неполное: можно отыскать протокол, который не забанен, можно поиграть с настройками, тем не менее хочется иметь возможность сделать это удалённо. Мой взгляд упал на нестандартные средства решения этой задачи.
Без внятного ТЗ, как известно, результат будет крайне неоднозначен. Поэтому сразу ставим цель. Целью будет возможность удалённо отдавать команды нашему домашнему linux-серверу, находящемуся за NAT через SSH и какой-нибудь веб-интерфейс. Для примера я возьму веб-интерфейс торрент-клиента transmission. Впрочем, со всем остальным, что работает в браузере схема будет аналогичная.
Сразу определимся с критериями.
Без дополнительных затрат. Будем использовать только бесплатные варианты, либо те, что уже есть в наличии под рукой.
Не зависит от экспортных ограничений и деструктивных действий регулирующих органов. По данному критерию, например, отпадает Zerotier. Хоть он и устанавливает связь p2p, тем не менее имеет централизованный сервис аутентификации. Блокировка сервиса аутентификации приведёт к невозможности использования без танцев с бубном.
Возможно скрыть от автоматических сканеров.
Из данных критериев можно сделать вывод, что для реализации данной схемы требуется децентрализованное решение на базе свободного ПО. Виртуальная частная сеть, которую мы обычно привыкли использовать для решения подобных задач является частным случаем оверлейной сети. Оверлейная сеть — это виртуальная сеть, построенная поверх другой сети. Она создаётся с использованием программных механизмов для абстрагирования физических соединений и позволяет пользователям или приложению взаимодействовать как будто они работают в единой, логически связанной сети, независимо от реальной структуры базовой сети.
Обычно, когда речь идёт об оверлейных сетях в качестве примеров, помимо всем понятных виртуальных частных сетей, приводят Tor, I2P, Yggdrasil. Рассмотрим решение нашей проблемы с использованием данных технологий.
Tor
Заблокирован в РФ. Несмотря на то, что блокировка обходится довольно просто, не подходит для наших целей по критерию номер 2. Однако для сравнения рассмотрим вариант решения нашей задачи через эту сеть. Техническая реализация уже была описана на хабре в этой статье, и с тех самых пор не изменялась.
В случае с ssh, команда для подключения с клиента будет выглядеть следующим образом:
torsocks ssh user@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.onion
При подключении по ssh в lastlog фигурирует адрес 127.0.0.1. Ограничить подключения с нежелательных адресов к псевдодоменному .onion-имени невозможно, то есть остаётся теоретическая уязвимость перед автосканерами. Однако, длина в 56 символов для псевдодомена делает его достаточно устойчивым к брутфорсу. Случайно подобрать активное onion-имя крайне сложно, а убедиться в его активности возможно только если достоверно знать порт, на котором работает HiddenService. Эффективных сканеров скрытых сервисов Tor я не нашёл. Считаю, что если установить нестандартный порт, можно быть в достаточной мере уверенным, что под автоскан наш сервер не попадёт. Но это если подходить к тексту ТЗ формально. Если рассматривать фаерволл как дополнительную ступень авторизации, то атакующий который уже знает ваш onion-адрес имеет все возможности достучаться до вашего сервера. В общем, здесь не так всё однозначно.
Yggdrasil
Если Tor в представлении не нуждается, то про Yggdrasil слышали не все. Оставлю ссылку на статью об этой сети и поехали дальше.
Устанавливаем на сервер и клиент согласно официальному мануалу.
После установки, взглянем на файл конфигурации:
/etc/yggdrasil/yggdrasil.conf
{
# Your private key. DO NOT share this with anyone!
PrivateKey: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
# List of outbound peer connection strings (e.g. tls://a.b.c.d:e or
# socks://a.b.c.d:e/f.g.h.i:j). Connection strings can contain options,
# see https://yggdrasil-network.github.io/configurationref.html#peers.
# Yggdrasil has no concept of bootstrap nodes - all network traffic
# will transit peer connections. Therefore make sure to only peer with
# nearby nodes that have good connectivity and low latency. Avoid adding
# peers to this list from distant countries as this will worsen your
# node's connectivity and performance considerably.
Peers: []
# List of connection strings for outbound peer connections in URI format,
# arranged by source interface, e.g. { "eth0": [ "tls://a.b.c.d:e" ] }.
# You should only use this option if your machine is multi-homed and you
# want to establish outbound peer connections on different interfaces.
# Otherwise you should use "Peers".
InterfacePeers: {}
# Listen addresses for incoming connections. You will need to add
# listeners in order to accept incoming peerings from non-local nodes.
# This is not required if you wish to establish outbound peerings only.
# Multicast peer discovery will work regardless of any listeners set
# here. Each listener should be specified in URI format as above, e.g.
# tls://0.0.0.0:0 or tls://[::]:0 to listen on all interfaces.
Listen: []
# Configuration for which interfaces multicast peer discovery should be
# enabled on. Regex is a regular expression which is matched against an
# interface name, and interfaces use the first configuration that they
# match against. Beacon controls whether or not your node advertises its
# presence to others, whereas Listen controls whether or not your node
# listens out for and tries to connect to other advertising nodes. See
# https://yggdrasil-network.github.io/configurationref.html#multicastinterfaces
# for more supported options.
MulticastInterfaces: [
{
Regex: .*
Beacon: true
Listen: true
Password: ""
}
]
# List of peer public keys to allow incoming peering connections
# from. If left empty/undefined then all connections will be allowed
# by default. This does not affect outgoing peerings, nor does it
# affect link-local peers discovered via multicast.
# WARNING: THIS IS NOT A FIREWALL and DOES NOT limit who can reach
# open ports or services running on your machine!
AllowedPublicKeys: []
# Local network interface name for TUN adapter, or "auto" to select
# an interface automatically, or "none" to run without TUN.
IfName: auto
# Maximum Transmission Unit (MTU) size for your local TUN interface.
# Default is the largest supported size for your platform. The lowest
# possible value is 1280.
IfMTU: 65535
# By default, nodeinfo contains some defaults including the platform,
# architecture and Yggdrasil version. These can help when surveying
# the network and diagnosing network routing problems. Enabling
# nodeinfo privacy prevents this, so that only items specified in
# "NodeInfo" are sent back if specified.
NodeInfoPrivacy: false
# Optional nodeinfo. This must be a { "key": "value", ... } map
# or set as null. This is entirely optional but, if set, is visible
# to the whole network on request.
NodeInfo: {}
}
Нам интересны только первые два параметра. Первый - PrivateKey. Рандомно генерируемое значение длиной в 128-знаков. Если максимально упрощать, именно от этого значения будет зависеть IPv6 - адрес, с которого вы будете выДанный конфиг мы устанавливаем как на сервере, так и на клиенте. Затем мы идём в файл /etc/i2pd/tunnels.conf на сервере. Удаляем всё его содержимое. и вставляем следующее:ходить в сеть. Запомним это, и двинемся дальше.
Второй параметр - Peers. В отличие от Tor, здесь нет такого понятия как Bootstrap nodes, которые отдают информацию о том, куда надо подключаться. Поэтому нам нужно добавить несколько адресов из числа публичных нод. Разработчики рекомендуют добавлять ноды, расположенные наиболее близко географически. Откроем список для России и сделаем, как рекомендуют разработчики.
Например:
Peers: [
tls://ygg-msk-1.averyan.ru:8362
tls://x-mow-0.sergeysedoy97.ru:65534
tcp://box.paulll.cc:13337
]
Производим данные манипуляции на сервере и на клиенте. Результат на скрине:
Однако! Мы только что объединили как сервер, так и клиент в единую сеть со всеми остальными пользователями Yggdrasil. К чему это может привести в условиях отсутствия фаерволла, можно прочитать здесь. Этот же фактор, собственно и нарушает критерий о недопустимости открытия доступа для различных сканеров. Но мы это можем поправить несколькими правилами ip6tables.
На сервере мы открываем доступ на нужные порты только для адреса нашего клиента, и дропаем всё остальное с интерфейса tun0 (именно на нём сидит Yggdrasil).
ip6tables -A INPUT -i tun0 -s 200:0000:0000:0000:0000:0000:0000:0000 -p tcp -m multiport --dports 22,9091 -j ACCEPT # Порты ssh и transmission-web
ip6tables -A INPUT -i tun0 -j DROP
Естественно, если клиентов несколько, то и правил добавляем несколько. Доступ к остальной сети Yggdrasil на сервере отключится. Это можно проверить запросом:
curl http://[201:30d4:d28:2185:b947:8817:cca5:ef95]/myip
Если ответа не получили, значит видеть вас может только клиент. Чего мы и добивались.
Клиентскую машину мы тоже выставили в сеть, поэтому на ней тоже добавляем правила. Оставим для себя возможность гулять по Yggdrasil, и забаним все коннекты извне.
# Установить политику по умолчанию:
# 1. Разрешить исходящий трафик (OUTPUT)
# 2. Разрешить пересылку трафика (FORWARD)
# 3. Заблокировать входящий трафик (INPUT)
ip6tables -P INPUT DROP
ip6tables -P FORWARD ACCEPT
ip6tables -P OUTPUT ACCEPT
# Разрешить входящие соединения на loopback-интерфейсе
ip6tables -A INPUT -i lo -j ACCEPT
# Разрешить входящий трафик, относящийся к уже установленным или связанным соединениям
ip6tables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# Разрешить исходящий трафик на интерфейсе tun0
ip6tables -A OUTPUT -o tun0 -j ACCEPT
# Заблокировать любой входящий трафик на интерфейсе tun0
ip6tables -A INPUT -i tun0 -j DROP
После применения правил на клиенте, убеждаемся, что всё работает именно так, как задумано следующим запросом:
curl http://[201:30d4:d28:2185:b947:8817:cca5:ef95]/check-port/80
Ответ должен быть:
{"host":"200:0000:0000:0000:0000:0000:0000:0000","port":80,"status":"State not found"}
Если значение status "open" или "closed", значит вы по какой-то причине всё ещё светитесь как новогодняя ёлка, привлекая желающих посканировать сеть, и это нужно исправить.
I2P
Здесь будет несколько посложнее с конфигурированием. В I2P нет IP-адресов как таковых. Только destination hash. Поэтому будем строить туннели.
Начинаем с уcтановки по мануалу от разработчиков. Расписывать её я, конечно, не буду.
Далее идём в конфиг, расположенный по адресу /etc/i2pd/i2pd.conf:
/etc/i2pd/i2pd.conf
## Configuration file for a typical i2pd user
## See https://i2pd.readthedocs.io/en/latest/user-guide/configuration/
## for more options you can use in this file.
## Lines that begin with "## " try to explain what's going on. Lines
## that begin with just "#" are disabled commands: you can enable them
## by removing the "#" symbol.
## Tunnels config file
## Default: ~/.i2pd/tunnels.conf or /var/lib/i2pd/tunnels.conf
# tunconf = /var/lib/i2pd/tunnels.conf
## Tunnels config files path
## Use that path to store separated tunnels in different config files.
## Default: ~/.i2pd/tunnels.d or /var/lib/i2pd/tunnels.d
# tunnelsdir = /var/lib/i2pd/tunnels.d
## Path to certificates used for verifying .su3, families
## Default: ~/.i2pd/certificates or /var/lib/i2pd/certificates
# certsdir = /var/lib/i2pd/certificates
## Where to write pidfile (default: /run/i2pd.pid, not used in Windows)
# pidfile = /run/i2pd.pid
## Logging configuration section
## By default logs go to stdout with level 'info' and higher
## For Windows OS by default logs go to file with level 'warn' and higher
##
## Logs destination (valid values: stdout, file, syslog)
## * stdout - print log entries to stdout
## * file - log entries to a file
## * syslog - use syslog, see man 3 syslog
# log = file
## Path to logfile (default: autodetect)
# logfile = /var/log/i2pd/i2pd.log
## Log messages above this level (debug, info, *warn, error, critical, none)
## If you set it to none, logging will be disabled
# loglevel = warn
## Write full CLF-formatted date and time to log (default: write only time)
# logclftime = true
## Daemon mode. Router will go to background after start. Ignored on Windows
## (default: true)
# daemon = true
## Specify a family, router belongs to (default - none)
# family =
## Network interface to bind to
## Updates address4/6 options if they are not set
# ifname =
## You can specify different interfaces for IPv4 and IPv6
# ifname4 =
# ifname6 =
## Local address to bind transport sockets to
## Overrides host option if:
## For ipv4: if ipv4 = true and nat = false
## For ipv6: if 'host' is not set or ipv4 = true
# address4 =
# address6 =
## External IPv4 or IPv6 address to listen for connections
## By default i2pd sets IP automatically
## Sets published NTCP2v4/SSUv4 address to 'host' value if nat = true
## Sets published NTCP2v6/SSUv6 address to 'host' value if ipv4 = false
# host = 1.2.3.4
## Port to listen for connections
## By default i2pd picks random port. You MUST pick a random number too,
## don't just uncomment this
# port = 4567
## Enable communication through ipv4 (default: true)
ipv4 = true
## Enable communication through ipv6 (default: false)
ipv6 = false
## Bandwidth configuration
## L limit bandwidth to 32 KB/sec, O - to 256 KB/sec, P - to 2048 KB/sec,
## X - unlimited
## Default is L (regular node) and X if floodfill mode enabled.
## If you want to share more bandwidth without floodfill mode, uncomment
## that line and adjust value to your possibilities. Value can be set to
## integer in kilobytes, it will apply that limit and flag will be used
## from next upper limit (example: if you set 4096 flag will be X, but real
## limit will be 4096 KB/s). Same can be done when floodfill mode is used,
## but keep in mind that low values may be negatively evaluated by Java
## router algorithms.
bandwidth = P
## Max % of bandwidth limit for transit. 0-100 (default: 100)
share = 20
## Router will not accept transit tunnels, disabling transit traffic completely
## (default: false)
# notransit = true
## Router will be floodfill (default: false)
## Note: that mode uses much more network connections and CPU!
# floodfill = true
[ntcp2]
## Enable NTCP2 transport (default: true)
# enabled = true
## Publish address in RouterInfo (default: true)
# published = true
## Port for incoming connections (default is global port option value)
# port = 4567
[ssu2]
## Enable SSU2 transport (default: true)
# enabled = true
## Publish address in RouterInfo (default: true)
# published = true
## Port for incoming connections (default is global port option value)
# port = 4567
[http]
## Web Console settings
## Enable the Web Console (default: true)
# enabled = true
## Address and port service will listen on (default: 127.0.0.1:7070)
# address = 127.0.0.1
# port = 7070
## Path to web console (default: /)
# webroot = /
## Enable Web Console authentication (default: false)
## You should not use Web Console via public networks without additional encryption.
## HTTP authentication is not encryption layer!
# auth = true
# user = i2pd
# pass = changeme
## Select webconsole language
## Currently supported english (default), afrikaans, armenian, chinese, czech, french,
## german, italian, polish, portuguese, russian, spanish, turkish, turkmen, ukrainian
## and uzbek languages
# lang = english
[httpproxy]
## Enable the HTTP proxy (default: true)
enabled = false
## Address and port service will listen on (default: 127.0.0.1:4444)
# address = 127.0.0.1
# port = 4444
## Optional keys file for proxy local destination (default: http-proxy-keys.dat)
# keys = http-proxy-keys.dat
## Enable address helper for adding .i2p domains with "jump URLs" (default: true)
## You should disable this feature if your i2pd HTTP Proxy is public,
## because anyone could spoof the short domain via addresshelper and forward other users to phishing links
# addresshelper = true
## Address of a proxy server inside I2P, which is used to visit regular Internet
# outproxy = http://false.i2p
## httpproxy section also accepts I2CP parameters, like "inbound.length" etc.
[socksproxy]
## Enable the SOCKS proxy (default: true)
enabled = false
## Address and port service will listen on (default: 127.0.0.1:4447)
# address = 127.0.0.1
# port = 4447
## Optional keys file for proxy local destination (default: socks-proxy-keys.dat)
# keys = socks-proxy-keys.dat
## Socks outproxy. Example below is set to use Tor for all connections except i2p
## Enable using of SOCKS outproxy (works only with SOCKS4, default: false)
# outproxy.enabled = false
## Address and port of outproxy
# outproxy = 127.0.0.1
# outproxyport = 9050
## socksproxy section also accepts I2CP parameters, like "inbound.length" etc.
[sam]
## Enable the SAM bridge (default: true)
enabled = false
## Address and ports service will listen on (default: 127.0.0.1:7656, udp: 7655)
# address = 127.0.0.1
# port = 7656
# portudp = 7655
[bob]
## Enable the BOB command channel (default: false)
# enabled = false
## Address and port service will listen on (default: 127.0.0.1:2827)
# address = 127.0.0.1
# port = 2827
[i2cp]
## Enable the I2CP protocol (default: false)
# enabled = false
## Address and port service will listen on (default: 127.0.0.1:7654)
# address = 127.0.0.1
# port = 7654
[i2pcontrol]
## Enable the I2PControl protocol (default: false)
# enabled = false
## Address and port service will listen on (default: 127.0.0.1:7650)
# address = 127.0.0.1
# port = 7650
## Authentication password (default: itoopie)
# password = itoopie
[precomputation]
## Enable or disable elgamal precomputation table
## By default, enabled on i386 hosts
# elgamal = true
[upnp]
## Enable or disable UPnP: automatic port forwarding (enabled by default in WINDOWS, ANDROID)
# enabled = false
## Name i2pd appears in UPnP forwardings list (default: I2Pd)
# name = I2Pd
[meshnets]
## Enable connectivity over the Yggdrasil network (default: false)
# yggdrasil = false
## You can bind address from your Yggdrasil subnet 300::/64
## The address must first be added to the network interface
# yggaddress =
[reseed]
## Options for bootstrapping into I2P network, aka reseeding
## Enable reseed data verification (default: true)
verify = true
## URLs to request reseed data from, separated by comma
## Default: "mainline" I2P Network reseeds
# urls = https://reseed.i2p-projekt.de/,https://i2p.mooo.com/netDb/,https://netdb.i2p2.no/
## Reseed URLs through the Yggdrasil, separated by comma
# yggurls = http://[324:71e:281a:9ed3::ace]:7070/
## Path to local reseed data file (.su3) for manual reseeding
# file = /path/to/i2pseeds.su3
## or HTTPS URL to reseed from
# file = https://legit-website.com/i2pseeds.su3
## Path to local ZIP file or HTTPS URL to reseed from
# zipfile = /path/to/netDb.zip
## If you run i2pd behind a proxy server, set proxy server for reseeding here
## Should be http://address:port or socks://address:port
# proxy = http://127.0.0.1:8118
## Minimum number of known routers, below which i2pd triggers reseeding (default: 25)
# threshold = 25
[addressbook]
## AddressBook subscription URL for initial setup
## Default: reg.i2p at "mainline" I2P Network
# defaulturl = http://shx5vqsw7usdaunyzr2qmes2fq37oumybpudrd4jjj4e4vk4uusa.b32.i2p/hosts.txt
## Optional subscriptions URLs, separated by comma
# subscriptions = http://reg.i2p/hosts.txt,http://identiguy.i2p/hosts.txt,http://stats.i2p/cgi-bin/newhosts.txt,http://rus.i2p/hosts.txt
[limits]
## Maximum active transit sessions (default: 5000)
## This value is doubled if floodfill mode is enabled!
# transittunnels = 5000
## Limit number of open file descriptors (0 - use system limit)
# openfiles = 0
## Maximum size of corefile in Kb (0 - use system limit)
# coresize = 0
[trust]
## Enable explicit trust options. (default: false)
# enabled = true
## Make direct I2P connections only to routers in specified Family.
# family = MyFamily
## Make direct I2P connections only to routers specified here. Comma separated list of base64 identities.
# routers =
## Should we hide our router from other routers? (default: false)
# hidden = true
[exploratory]
## Exploratory tunnels settings with default values
# inbound.length = 2
# inbound.quantity = 3
# outbound.length = 2
# outbound.quantity = 3
[persist]
## Save peer profiles on disk (default: true)
# profiles = true
## Save full addresses on disk (default: true)
# addressbook = true
В дефолтном конфиге I2P я обычно меняю следующие параметры:
bandwidth = P
# Расширяю канал с 32 до 2048 килобайт в секунду.
share = 20
# Режу канал для транзитного трафика до 20%. Я не против помочь сети, но в разумных пределах.
# notransit = true
# А если лично вы не хотите, чтобы через ваш канал гоняли зашифрованные байты, вы можете раскомментировать параметр notransit, установив его в значение true.
[httpproxy]
enabled = false
[socksproxy]
enabled = false
[sam]
enabled = false
# Выключаю всё, что не нужно для выполнения нашей задачи.
Данный конфиг мы устанавливаем как на сервере, так и на клиенте. Затем мы идём в файл /etc/i2pd/tunnels.conf на сервере. Удаляем всё его содержимое. и вставляем следующее:
[SSH]
type = server
host = 127.0.0.1
port = 22
inbound.length = 0
outbound.length = 0
inbound.quantity = 5
outbound.quantity = 5
keys = ssh.dat
[transmission-in]
type = http
host = 127.0.0.1
port = 9091
inbound.length = 0
outbound.length = 0
inbound.quantity = 5
outbound.quantity = 5
keys = transmission.dat
Здесь мы создаём два туннеля. Generic TCP туннель для SSH и HTTP туннель для transmission-web. Отключаем промежуточные точки, это убивает анонимность, но для нас это не важно, так как мы коннектимся к своему же серверу. Рестартим I2P на сервере и заходим в веб-админку, которая по дефолту находится на 127.0.0.1:7070. В админке мы кликаем на вкладку I2P tunnels.
Видим два base32 адреса, один для ssh, второй для transmission. Они нам пригодятся.
На клиенте также создаём туннели, только уже клиентские.
[SSH]
type = client
address = 127.0.0.1
port = 10022
destination = r00000000000000000000000000000000000000000000000000a.b32.i2p
destinationport = 22
keys = ssh.dat
[transmission-web]
type = client
address = 127.0.0.1
port = 10091
destination = p00000000000000000000000000000000000000000000000000a.b32.i2p
destinationport = 9091
keys = transmission.dat
Параметры address и port указывают где локально будет открываться туннель. Destination, вместе с портом - удалённый адрес сервера, полученный на прошлом шаге из админки. Перезапускаем i2p-роутер на клиенте, и после этого идём на вкладку I2P tunnels.
Здесь мы видим адреса туннелей для клиента. В интерфейсе сразу видно, входящий это туннель или исходящий. И сейчас мы будем ограничивать доступ на наш сервер для желающих постучаться извне. Возвращаемся в файл с настройками туннелей на сервере и добавляем параметр accesslist. Значением указываем адрес клиентского туннеля без b32.i2p.
[SSH]
type = server
host = 127.0.0.1
port = 22
inbound.length = 0
outbound.length = 0
inbound.quantity = 5
outbound.quantity = 5
keys = ssh.dat
accesslist = l00000000000000000000000000000000000000000000000000q
[transmission-in]
type = http
host = 127.0.0.1
port = 9091
inbound.length = 0
outbound.length = 0
inbound.quantity = 5
outbound.quantity = 5
keys = transmission.dat
accesslist = 500000000000000000000000000000000000000000000000000a
В случае наличия нескольких клиентов, добавляем адреса их всех, разделяя запятой.
Для тех, кто ни разу не сталкивался с I2P, поясняю. Несмотря на то, что подключение идёт по адресу 127.0.0.1, мы здесь подключаемся именно к удалённому туннелю. Запись lastlog с ip из сети 127.0.0.0/8 выглядит, на мой взгляд, весьма забавно. Задача выполнена: к серверу можно подключиться исключительно с одобренного клиента.
Подведём итог. В текущих условиях сложно организовать отказоустойчивый доступ к удалённому серверу. Однако же, я считаю маловероятной ситуацию при которой будут заблокированы все оверлейные протоколы одновременно (за исключением полного шатдауна). Организация резервного канала связи нестандартными средствами даст возможность при необходимости оперативно изменить схему подключения без физического доступа к серверу.
Комментарии (0)
IRT
20.01.2025 10:15А зачем такие извращения? Тот же Wireguard банится только при коннектах за границу, на свой домашний роутер в РФ спокойно по нему можно зайти. Zerotier недавно добавили в Keenetic, тоже не банится внутри страны (да и за пределами тоже).
HomeMan
20.01.2025 10:15В статье есть ключевое слово NAT от провайдера. И на свой роутер Вы не зайдете, если Ваш провайдер держит Вас за натом. Мой например держит порядка 10к пользователей за натом. У всех 10к один IP адрес. Да, такое есть сплошь, и рядом.
NeoCode
А как вообще на низком уровне осуществляется обход NAT? Допустим у меня есть два компьютера, подключенные к разным провайдерам, оба за NAT. И я хочу их соединить скажем по протоколу UDP. Простейшая самописная программка, умеющая отправлять и получать UDP пакеты. C одного отправляем пакет - на другом получаем. Что для этого нужно сделать? При этом у меня нет никакого внешнего сервера со статическим IP.
Sfinx88
NAT не блокирует связь полностью. Это как бы динамическая трансляция определенного внешнего порта на определённый внутренний порт определенного клиента, сидящего за NAT. Не понятно? Допустим твой браузер стучится на определенный ip на порт 80. Для этого твой комп открывает внешний порт и стучится в дефолный шлюз, который видя такой запрос открывает внешний порт и пересылает пакет. Куда? а на свой дефолтный шлюз, где цепочка повторяется. Как ответный пакет идет назад? А просто: вместе с выходным портом открывается входной, который и транслируется на входной порт предыдущего клиента NAT. Так ответ сервера добирается до твоего компа. Поэтому обойди Nat без внешнего сервера в принципе невозможно, кто-то должен сообщить этот динамический входной порт. Пусть даже сам трафик через этот промежуточный не гнать....