Классический форум-трекер
canvas not supported
Нас вместе: 4 078 282

Использование связки DNScrypt-proxy + TOR на роутере с OpenWRT


 
 
RSS
Начать новую тему   Ответить на тему    Торрент-трекер NNM-Club -> Обход блокировок
Автор Сообщение
xruyn ®
Стаж: 4 года 11 мес.
Сообщений: 16
Ratio: 44,612
Раздал: 16,84 TB
Поблагодарили: 92
100%
Доброе время суток уважаемые одноклубники. Хочу поделиться с вами универсальным способом захода на сайты из списка заблокированных адресов.
Этот способ предполагает установку связки программного обеспечения DNSCrypt + Tor на роутер с поддержкой прошивки OpenWRT - альтернативная прошивка на базе Linux для многих моделей роутеров. Список поддерживаемых устройств можно посмотреть здесь - https://openwrt.org/toh/start
Основным требованием к роутеру является минимальное наличие примерно 8 МБ свободной flash-памяти (можно расширить за счет внешнего USB носителя) и минимально 64 МБ оперативной памяти. А лучше больше.
Все описываемое проводилось на роутере DIR-835 ver.A1 с прошивкой OpenWRT 15.05.1. Но так же принципиально подходит как для более ранних, так и для более поздних версий прошивки (проект LEDE).
Таким образом, отправной точкой для работ является наличие роутера с прошивкой OpenWRT и примерно часа свободного времени. Из инструментов на компьютере нужен любой SSH-клиент.
Вкратце, что делает данный способ: на роутере формируется список с IP адресами заблокированных сайтов, который берется с сайта antizapret. Роутер смотрит попадает ли запрашиваемый вами адрес в этот список. Если попадает, то гонит трафик через TOR, если нет, то через обычную сеть. Кроме того, пакет DNScrypt-proxy перенаправляет ваш DNS-запрос на сторонний заграничный сервер в зашифрованном виде. Это исключает подмену DNS адреса со стороны вашего провайдера.
Подключаемся к роутеру по SSH с логином root и вашим паролем. Попадаем в консоль. Все остальное разделил на три блока.
1. Подготовительный этап
opkg update (обновление пакетов)
opkg install nano (поставим редактор nano)
opkg remove dnsmasq (удаляет старый пакет)
rm /etc/config/dhcp (удаляет оставшиеся файлы от пакета)
rm /etc/dnsmasq.conf
opkg install dnsmasq-full (устанавливает новую версию пакета)
2. Установка DNScrypt-proxy
Источник
opkg install dnscrypt-proxy (пакет DNScrypt-proxy)
cd /usr/share/dnscrypt-proxy
mv dnscrypt-resolvers.csv dnscrypt-resolvers.csv_ori
tr -d '\r' <dnscrypt-resolvers.csv_ori >dnscrypt-resolvers.csv
rm dnscrypt-resolvers.csv_ori

Правим конфиг DNScrypt

nano /etc/config/dnscrypt-proxy

Он должен быть приведен к виду

config dnscrypt-proxy
option address '127.0.0.1'
option port '2053'
option resolver 'opendns'
option resolvers_list /usr/share/dnscrypt-proxy/dnscrypt-resolvers.csv'

В более новых пакетах DNScrypt-proxy (в прошивках LEDE) нет сервера opendns. Надо использовать другой сервер.

Правим конфиг DHCP

nano /etc/config/dhcp

В секцию dnsmasq (этого config dnsmasq) файла надо внести две строчки

option noresolv '1'
list server '127.0.0.1#2053'
list server '/pool.ntp.org/208.67.222.222'

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

nano /etc/rc.local

перед строкой exit 0 добавить

sleep 10
/etc/init.d/dnscrypt-proxy start

Теперь можно перегрузить роутер

reboot

После перезагрузки, подключившись по SSH, проверим работает ли пакет. Введите

logread | grep -n "using nameserver"


Вывод должен быть примерно такой

........ openwrt daemon.info dnsmasq[13292]: using nameserver 208.67.222.222#53 for domain pool.ntp.org
........ openwrt daemon.info dnsmasq[13292]: using nameserver 127.0.0.1#2053

И команду

logread | grep "Proxying from"

Вывод примерно такой

........ openwrt daemon.info dnscrypt-proxy[13289]: Proxying from 127.0.0.1:2053 to 208.67.220.220:443

Еще можно пройти Extended тест на этом сайте https://www.dnsleaktest.com/

Если все это есть, то можно приступать к следующему шагу - установке и настройке TOR.
3. Установка TOR
Источник
opkg update
opkg install ipset (пакеты для формирования списка IP адресов)
opkg install luasocket
opkg install luabitop
opkg install tor (установка самого TOR)

Далее нужен пакет tor-geoip. В моем случае его не было в репозитории. Пришлось брать от другой версии OpenWRT

opkg install http://archive.openwrt.org/chaos_calmer/15.05/ar71xx/generic/packages/packages/tor-geoip_0.2.5.12-1_ar71xx.ipk

После этого обязательно перегрузите роутер

reboot

После перезагрузки продолжаем по SSH
Открыть файл idn.lua, скопировать его содержимое. Создать файл

nano /usr/lib/lua/idn.lua

И вставить скопированный текст правой кнопкой мыши. Сохранить файл.

Открыть текст ниже, скопировать его
local config = {
blSource = "antizapret", -- antizapret или rublacklist
groupBySld = 32, -- количество поддоменов после которого в список вносится весь домен второго уровня целиком
neverGroupMasks = { "^%a%a%a?.%a%a$" }, -- не распространять на org.ru, net.ua и аналогичные
neverGroupDomains = { ["livejournal.com"] = true, ["facebook.com"] = true , ["vk.com"] = true },
stripWww = true,
convertIdn = true,
torifyNsLookups = false, -- отправлять DNS запросы заблокированных доменов через TOR
blMinimumEntries = 1000, -- костыль если список получился короче, значит что-то пошло не так и конфиги не обновляем
dnsmasqConfigPath = "/etc/runblock/runblock.dnsmasq",
ipsetConfigPath = "/etc/runblock/runblock.ipset",
ipsetDns = "rublack-dns",
ipsetIp = "rublack-ip",
torDnsAddr = "127.0.0.1#9053"
}

local function prequire(package)
local result, err = pcall(function() require(package) end)
if not result then
return nil, err
end
return require(package) -- return the package value
end

local idn = prequire("idn")
if (not idn) and (config.convertIdn) then
error("you need either put idn.lua (github.com/haste/lua-idn) in script dir or set 'convertIdn' to false")
end

local http = prequire("socket.http")
if not http then
local ltn12 = require("ltn12")
end
if not ltn12 then
error("you need either install luasocket package (prefered) or put ltn12.lua in script dir")
end

local function hex2unicode(code)
local n = tonumber(code, 16)
if (n < 128) then
return string.char(n)
elseif (n < 2048) then
return string.char(192 + ((n - (n % 64)) / 64), 128 + (n % 64))
else
return string.char(224 + ((n - (n % 4096)) / 4096), 128 + (((n % 4096) - (n % 64)) / 64), 128 + (n % 64))
end
end

local function rublacklistExtractDomains()
local currentRecord = ""
local buffer = ""
local bufferPos = 1
local streamEnded = false
return function(chunk)
local retVal = ""
if chunk == nil then
streamEnded = true
else
buffer = buffer .. chunk
end

while true do
local escapeStart, escapeEnd, escapedChar = buffer:find("\\(.)", bufferPos)
if escapedChar then
currentRecord = currentRecord .. buffer:sub(bufferPos, escapeStart - 1)
bufferPos = escapeEnd + 1
if escapedChar == "n" then
retVal = currentRecord
break
elseif escapedChar == "u" then
currentRecord = currentRecord .. "\\u"
else
currentRecord = currentRecord .. escapedChar
end
else
currentRecord = currentRecord .. buffer:sub(bufferPos, #buffer)
buffer = ""
bufferPos = 1
if streamEnded then
if currentRecord == "" then
retVal = nil
else
retVal = currentRecord
end
end
break
end
end
if retVal and (retVal ~= "") then
currentRecord = ""
retVal = retVal:match("^[^;]*;([^;]+);[^;]*;[^;]*;[^;]*;[^;]*.*$")
if retVal then
retVal = retVal:gsub("\\u(%x%x%x%x)", hex2unicode)
else
retVal = ""
end
end
return (retVal)
end
end

local function antizapretExtractDomains()
local currentRecord = ""
local buffer = ""
local bufferPos = 1
local streamEnded = false
return function(chunk)
local haveOutput = 0
local retVal = ""
if chunk == nil then
streamEnded = true
else
buffer = buffer .. chunk
end
local newlinePosition = buffer:find("\n", bufferPos)
if newlinePosition then
currentRecord = currentRecord .. buffer:sub(bufferPos, newlinePosition - 1)
bufferPos = newlinePosition + 1
retVal = currentRecord
else
currentRecord = currentRecord .. buffer:sub(bufferPos, #buffer)
buffer = ""
bufferPos = 1
if streamEnded then
if currentRecord == "" then
retVal = nil
else
retVal = currentRecord
end
end
end
if retVal and (retVal ~= "") then
currentRecord = ""
end
return (retVal)
end
end

local function normalizeFqdn()
return function(chunk)
if chunk and (chunk ~= "") then
if config["stripWww"] then chunk = chunk:gsub("^www%.", "") end
if idn and config["convertIdn"] then chunk = idn.encode(chunk) end
if #chunk > 255 then chunk = "" end
chunk = chunk:lower()
end
return (chunk)
end
end

local function cunstructTables(bltables)
bltables = bltables or { fqdn = {}, sdcount = {}, ips = {} }
local f = function(blEntry, err)
if blEntry and (blEntry ~= "") then
if blEntry:match("^%d+%.%d+%.%d+%.%d+$") then
-- ip адреса - в отдельную таблицу для iptables
if not bltables.ips[blEntry] then
bltables.ips[blEntry] = true
end
else
-- как можем проверяем, FQDN ли это. заодно выделяем домен 2 уровня (если в bl станут попадать TLD - дело плохо :))
local subDomain, secondLevelDomain = blEntry:match("^([a-z0-9%-%.]-)([a-z0-9%-]+%.[a-z0-9%-]+)$")
if secondLevelDomain then
bltables.fqdn[blEntry] = secondLevelDomain
if 1 > 0 then
bltables.sdcount[secondLevelDomain] = (bltables.sdcount[secondLevelDomain] or 0) + 1
end
end
end
end
return 1
end
return f, bltables
end

local function compactDomainList(fqdnList, subdomainsCount)
local domainTable = {}
local numEntries = 0
if config.groupBySld and (config.groupBySld > 0) then
for sld in pairs(subdomainsCount) do
if config.neverGroupDomains[sld] then
subdomainsCount[sld] = 0
break
end
for _, pattern in ipairs(config.neverGroupMasks) do
if sld:find(pattern) then
subdomainsCount[sld] = 0
break
end
end
end
end
for fqdn, sld in pairs(fqdnList) do
if (not fqdnList[sld]) or (fqdn == sld) then
local keyValue;
if config.groupBySld and (config.groupBySld > 0) and (subdomainsCount[sld] > config.groupBySld) then
keyValue = sld
else
keyValue = fqdn
end
if not domainTable[keyValue] then
domainTable[keyValue] = true
numEntries = numEntries + 1
end
end
end
return domainTable, numEntries
end

local function generateDnsmasqConfig(configPath, domainList)
local configFile = assert(io.open(configPath, "w"), "could not open dnsmasq config")
for fqdn in pairs(domainList) do
if config.torifyNsLookups then
configFile:write(string.format("server=/%s/%s\n", fqdn, config.torDnsAddr))
end
configFile:write(string.format("ipset=/%s/%s\n", fqdn, config.ipsetDns))
end
configFile:close()
end

local function generateIpsetConfig(configPath, ipList)
local configFile = assert(io.open(configPath, "w"), "could not open ipset config")
configFile:write(string.format("flush %s-tmp\n", config.ipsetIp))
for ipaddr in pairs(ipList) do
configFile:write(string.format("add %s %s\n", config.ipsetIp, ipaddr))
end
configFile:write(string.format("swap %s %s-tmp\n", config.ipsetIp, config.ipsetIp))
configFile:close()
end

local retVal, retCode, url

local output, bltables = cunstructTables()
if config.blSource == "rublacklist" then
output = ltn12.sink.chain(ltn12.filter.chain(rublacklistExtractDomains(), normalizeFqdn()), output)
url = "http://reestr.rublacklist.net/api/current"
elseif config.blSource == "antizapret" then
output = ltn12.sink.chain(ltn12.filter.chain(antizapretExtractDomains(), normalizeFqdn()), output)
url = "http://api.antizapret.info/group.php?data=domain"
else
error("blacklist source should be either 'rublacklist' or 'antizapret'")
end

if http then
retVal, retCode = http.request { url = url, sink = output }
else
retVal, retCode = ltn12.pump.all(ltn12.source.file(io.popen("wget -qO- " .. url)), output)
end

if (retVal == 1) and ((retCode == 200) or (http == nil)) then
local domainTable, recordsNum = compactDomainList(bltables.fqdn, bltables.sdcount)
if recordsNum > config.blMinimumEntries then
generateDnsmasqConfig(config.dnsmasqConfigPath, domainTable)
generateIpsetConfig(config.ipsetConfigPath, bltables.ips)
print(string.format("blacklists updated. %d entries.", recordsNum))
os.exit(0)
end
end
os.exit(1)
и вставить в файл

nano /usr/bin/rublupdate.lua

Правка DNSmasq

nano /etc/dnsmasq.conf

Добавить

server=/onion/127.0.0.1#9053
ipset=/onion/onion
conf-file=/etc/runblock/runblock.dnsmasq

Правим DHCP

nano /etc/config/dhcp

В секцию dnsmasq добавить одну строчку

list rebind_domain 'onion'

Создадим правила для сетевого экрана firewall. Открыть текст ниже. Скопировать его содержимое и вставить в файл firewall (я вставил в конец файла)
config ipset
option name 'rublack-dns'
option storage 'hash'
option match 'dest_ip'
option timeout '86400'

config ipset
option name 'rublack-ip'
option storage 'hash'
option match 'dest_ip'

config ipset
option name 'rublack-ip-tmp'
option storage 'hash'
option match 'dest_ip'

config ipset
option name 'onion'
option storage 'hash'
option match 'dest_ip'
option timeout '86400'

config redirect
option name 'torify-blocked-dns'
option src 'lan'
option proto 'tcp'
option ipset 'rublack-dns'
option dest_port '9040'
option dest 'lan'

config redirect
option name 'torify-blocked-ip'
option src 'lan'
option proto 'tcp'
option ipset 'rublack-ip'
option dest_port '9040'
option dest 'lan'

config redirect
option name 'torify-onion'
option src 'lan'
option proto 'tcp'
option ipset 'onion'
option dest_port '9040'
option dest 'lan'
nano /etc/config/firewall

Правим

nano /etc/firewall.user

Добавим одну строчку в конец файла

cat /etc/runblock/runblock.ipset | ipset restore

Создадим каталог

mkdir /etc/runblock

Настроим TOR

nano /etc/tor/torrc

Вставить в конец следующие строки

User tor
PidFile /var/run/tor.pid
DataDirectory /var/lib/tor
ExcludeExitNodes {RU}, {BY}, {KZ}, {UA}
VirtualAddrNetwork 10.254.0.0/16
AutomapHostsOnResolve 1
TransPort 9040
TransListenAddress 127.0.0.1
TransListenAddress 192.168.1.1 #адрес вашего роутера - НЕОБХОДИМО ПОМЕНЯТЬ
DNSPort 9053
DNSListenAddress 127.0.0.1

Запускаем скрипт, который сформирует список IP адресов

lua /usr/bin/rublupdate.lua

Он должен отработать без ошибок и в конце выдать количество адресов (примерно 60000).

После этого надо перегрузить роутер

reboot

После перезагрузки устройства через пару минут можно пробовать зайти куда вам надо. Все описанное является общим случаем настройки и подходит в 90% случаев. Частные случае настройки (версии прошивок, модели роутеров и т.д.) надо смотреть отдельно.
Показать сообщения:   
Начать новую тему   Ответить на тему    Торрент-трекер NNM-Club -> Обход блокировок Часовой пояс: GMT + 3
Страница 1 из 1