TLS पर DNS - Stunnel और Lua का उपयोग करके हमारे DNS प्रश्नों को एन्क्रिप्ट करें


छवि स्रोत


DNS (Eng। डोमेन नाम प्रणाली - डोमेन नामों की एक प्रणाली) - डोमेन के बारे में जानकारी प्राप्त करने के लिए एक वितरित कंप्यूटर प्रणाली।

टीएलएस ( ट्रांसपोर्ट लेयर सिक्योरिटी प्रोटोकॉल) - इंटरनेट नोड्स के बीच सुरक्षित डेटा ट्रांसफर प्रदान करता है।

समाचार के बाद, "Google सार्वजनिक डीएनएस चुपचाप टीएलएस समर्थन पर डीएनएस को चालू कर दिया," मैंने इसे आज़माने का फैसला किया। मेरे पास एक Stunnel है जो एक एन्क्रिप्टेड TCP सुरंग बनाएगा। लेकिन प्रोग्राम आमतौर पर यूडीपी प्रोटोकॉल का उपयोग करके डीएनएस के साथ संवाद करते हैं। इसलिए, हमें एक प्रॉक्सी की आवश्यकता है जो टीसीपी स्ट्रीम से यूडीपी पैकेटों को आगे और पीछे करेगी। हम इसे लूआ पर लिखेंगे।


टीसीपी और यूडीपी डीएनएस पैकेट के बीच पूरा अंतर:


4.2.2। टीसीपी का उपयोग
टीसीपी कनेक्शन पर भेजे गए संदेश सर्वर पोर्ट 53 (दशमलव) का उपयोग करते हैं। संदेश दो बाइट लंबाई फ़ील्ड के साथ उपसर्ग है जो संदेश को लंबाई देता है, दो बाइट लंबाई फ़ील्ड को छोड़कर। यह लंबाई फ़ील्ड निम्न स्तर के प्रसंस्करण को पूर्ण संदेश को पार्स करने की शुरुआत से पहले इकट्ठा करने की अनुमति देता है।

RFC1035: DOMAIN NAMES - प्रभाव और विशिष्टता


यही है, हम वहाँ करते हैं:


  1. हम UDP से एक पैकेट लेते हैं
  2. इसे शुरुआत में जोड़े बाइट्स के एक जोड़े में जिसमें इस पैकेट का आकार इंगित किया गया है
  3. टीसीपी चैनल को भेजें

और विपरीत दिशा में:


  1. हम TCP से कुछ बाइट्स पढ़ते हैं, हमें पैकेट का आकार मिलता है
  2. हम टीसीपी से एक पैकेट पढ़ते हैं
  3. इसे UDP के माध्यम से प्राप्तकर्ता को भेजें

Stunnel अनुकूलित करें


  1. रूट सर्टिफिकेट रूट- R2.crt को निर्देशिका में Stunnel config के साथ डाउनलोड करें
  2. प्रमाणपत्र को पीईएम में परिवर्तित करें
    openssl x509 -inform DER -in Root-R2.crt -out Root-R2.pem -text 
  3. हम stunnel.conf में लिखते हैं:


     [dns] client = yes accept = 127.0.0.1:53 connect = 8.8.8.8:853 CAfile = Root-R2.pem verifyChain = yes checkIP = 8.8.8.8 


यही है, Stunnel:


  1. 127.0.0.1:53 पर अनएन्क्रिप्टेड टीसीपी स्वीकार करेंगे
  2. 8.8.8.8:853 (Google DNS) को संबोधित करने के लिए एक एन्क्रिप्टेड टीएलएस सुरंग खोलेगा
  3. आगे और पीछे डेटा ट्रांसफर करेगा

Stunnel लॉन्च करें


सुरंग के संचालन को कमांड से जांचा जा सकता है:


 nslookup -vc ya.ru 127.0.0.1 

UDP के बजाय DNS सर्वर के लिए TCP कनेक्शन का उपयोग करने के लिए -vc विकल्प nslookup को बाध्य करता है।


परिणाम:


 *** Can't find server name for address 127.0.0.1: Non-existent domain Server: UnKnown Address: 127.0.0.1 Non-authoritative answer: Name: ya.ru Address: ( IP ) 

पटकथा लिखना


मैं लुआ 5.3 में लिख रहा हूँ। संख्याओं के साथ द्विआधारी संचालन इसमें पहले से ही उपलब्ध हैं। खैर, हमें लुआ सॉकेट मॉड्यूल की आवश्यकता होगी।


फ़ाइल नाम: सरल-udp-to-tcp-dns -xy.lua


 local socket = require "socket" --  lua socket 

--[[--


आइए एक सरल फ़ंक्शन लिखें जो आपको कंसोल पर एक डंप पैकेज भेजने की अनुमति देगा। मैं देखना चाहता हूं कि प्रॉक्सी क्या करती है।


--]]--


 function serialize(data) --       az  0-9    HEX  '\xFF' return "'"..data:gsub("[^a-z0-9-]", function(chr) return ("\\x%02X"):format(chr:byte()) end).."'" end 

--[[--


UDP को TCP और वापस


हम दो फ़ंक्शन लिखते हैं जो दो डेटा ट्रांसमिशन चैनलों के साथ काम करेंगे।


--]]--


 --    UDP   TCP  function udp_to_tcp_coroutine_function(udp_in, tcp_out, clients) repeat coroutine.yield() --     packet, err_ip, port = udp_in:receivefrom() --  UDP  if packet then -- > - big endian -- I - unsigned integer -- 2 - 2 bytes size tcp_out:send(((">I2"):pack(#packet))..packet) --       TCP local id = (">I2"):unpack(packet:sub(1,2)) --  ID  if not clients[id] then clients[id] = {} end table.insert(clients[id] ,{ip=err_ip, port=port, packet=packet}) --    print(os.date("%c", os.time()) ,err_ip, port, ">", serialize(packet)) --     end until false end --    TCP      UDP function tcp_to_udp_coroutine_function(tcp_in, udp_out, clients) repeat coroutine.yield() --     -- > - big endian -- I - unsigned integer -- 2 - 2 bytes size local packet = tcp_in:receive((">I2"):unpack(tcp_in:receive(2)), nil) --  TCP  local id = (">I2"):unpack(packet:sub(1,2)) --  ID  if clients[id] then for key, client in pairs(clients[id]) do --  query     if packet:find(client.packet:sub(13, -1), 13, true) == 13 then --   udp_out:sendto(packet, client.ip, client.port) --     UDP clients[id][key] = nil --   --     print(os.date("%c", os.time()) ,client.ip, client.port, "<", serialize(packet)) break end end if not next(clients[id]) then clients[id] = nil end end until false end 

--[[--


दोनों फ़ंक्शन लॉन्च के तुरंत बाद coroutine.yield () निष्पादित करते हैं। यह आपको फ़ंक्शन के मापदंडों को पहली कॉल में पास करने की अनुमति देता है और फिर अतिरिक्त मापदंडों के बिना coroutine.resume (co) करता है।


मुख्य


और अब मुख्य कार्य जो मुख्य लूप तैयार करेगा और शुरू करेगा।


--]]--


 function main() local tcp_dns_socket = socket.tcp() --  TCP  local udp_dns_socket = socket.udp() --  UDP  local tcp_connected, err = tcp_dns_socket:connect("127.0.0.1", 53) --   TCP  assert(tcp_connected, err) --    print("tcp dns connected") --      local udp_open, err = udp_dns_socket:setsockname("127.0.0.1", 53) --  UDP  assert(udp_open, err) --    print("udp dns port open") --   UDP   --     Lua        nil --              local coroutines = { [tcp_dns_socket] = coroutine.create(tcp_to_udp_coroutine_function), --   TCP to UDP [udp_dns_socket] = coroutine.create(udp_to_tcp_coroutine_function) --   UDP to TCP } local clients = {} --      --        coroutine.resume(coroutines[tcp_dns_socket], tcp_dns_socket, udp_dns_socket, clients) coroutine.resume(coroutines[udp_dns_socket], udp_dns_socket, tcp_dns_socket, clients) --    socket.select        local socket_list = {tcp_dns_socket, udp_dns_socket} repeat --    -- socket.select   socket_list          --      .  for       for _, in_socket in ipairs(socket.select(socket_list)) do --       local ok, err = coroutine.resume(coroutines[in_socket]) if not ok then --       udp_dns_socket:close() --  UDP  tcp_dns_socket:close() --  TCP  print(err) --   return --    end end until false end 

--[[--


हम मुख्य कार्य का शुभारंभ करते हैं। यदि कनेक्शन अचानक बंद हो जाता है, तो एक सेकंड के बाद हम इसे मुख्य कॉल करके फिर से स्थापित करेंगे।


--]]--


 repeat local ok, err = coroutine.resume(coroutine.create(main)) --  main if not ok then print(err) end socket.sleep(1) --      until false 

चेक


  1. दौड़ना stunnel


  2. हमारी स्क्रिप्ट चलाओ


     lua5.3 simple-udp-to-tcp-dns-proxy.lua 

  3. कमांड के साथ स्क्रिप्ट ऑपरेशन की जांच करें


     nslookup ya.ru 127.0.0.1 

    इस बार, '-vc' के बिना, यह है कि हमने कैसे प्रॉक्सी को लिखा और शुरू किया, जो टीसीपी सुरंग में यूडीपी डीएनएस अनुरोधों को लपेटता है।



परिणाम:


 *** Can't find server name for address 127.0.0.1: Non-existent domain Server: UnKnown Address: 127.0.0.1 Non-authoritative answer: Name: ya.ru Address: ( IP ) 

यदि सब कुछ ठीक है, तो आप कनेक्शन सेटिंग्स में DNS सर्वर "127.0.0.1" के रूप में निर्दिष्ट कर सकते हैं


निष्कर्ष


अब हमारे DNS प्रश्नों को TLS द्वारा संरक्षित किया जाता है।


PS हम अपने बारे में Google को अतिरिक्त जानकारी नहीं देते हैं


कनेक्शन के ठीक बाद, विंडोज हमारी सुरंग के माध्यम से हमें Google के DNS सर्वरों पर पंजीकृत करने की कोशिश करता है। यह अनचेक करके उन्नत DNS सेटिंग्स में अक्षम है।



अभी भी time.windows.com के लिए अनुरोध है। वह अब इतना व्यक्तिगत नहीं है, लेकिन मैंने कभी नहीं पाया कि इसे कैसे बंद किया जाए। स्वचालित समय सिंक्रनाइज़ेशन अक्षम है।


संदर्भ


  1. RFC1035: DOMAIN NAMES - प्रभाव और विशिष्टता
  2. टीएलएस पर डीएनएस
  3. सरल-यूडीपी-टू-tcp- DNS-proxy.lua
  4. DNS क्वेरी को मैन्युअल रूप से लिखें

Source: https://habr.com/ru/post/hi427957/


All Articles