Your new topic does not fit any of the above??? Check first. Then post here. Thanks.

Moderator: igrr

User avatar
By SwiCago
#20627 Hi, been using the esp-01 and esp-07 to host webpages to control GPIO pins.
I set them up in AP mode and connect with a table or phone. Then I enter the IP address of the ESP to browse the webpage it hosts.
Is there a way to setup the esp as an AP, but make it call a start page (CAPTIVE PORTAL) or force all DNS requests to resolve to the ESPs IP address?
Just to clarify, I do not want the ESP as a client and connect to a captive portal, but rather the ESP to be a AP and host a captive portal.
Thanks in advance
User avatar
By burkmurray
#20644 I've got this (mostly) working, using the new DNSserver library: https://github.com/esp8266/Arduino/tree/esp8266-sdk-1.0/hardware/esp8266com/esp8266/libraries/DNSServer

By default, the library only handles requests for a specified URL (e.g., example.com), but you can easily modify DNSServer.cpp to get you most of the way:

Code: Select all// Original
//    if (_dnsHeader->QR == DNS_QR_QUERY &&
//        _dnsHeader->OPCode == DNS_OPCODE_QUERY &&
//        requestIncludesOnlyOneQuestion() &&
//        getDomainNameWithoutWwwPrefix() == _domainName)

// Modified to remove domainName check - Works! - but doesnt handle domain subdirs
    if (_dnsHeader->QR == DNS_QR_QUERY &&
        _dnsHeader->OPCode == DNS_OPCODE_QUERY &&
        requestIncludesOnlyOneQuestion())


This will redirect any simple domain name (e.g., example.com, fu.bar, etc), but it doesn't handle a URL with a web page attached (e.g., example.com/examples) - or, rather, it redirects the domain and sends the page request to your server, which chokes on it.

I've asked the DNSServer library author to consider adding a captive portal function, and I'm hoping to have time later this week to play with it more - it seems like it ought to be easy to strip the page request.

Anyone have a suggestion for how to approach the problem?
User avatar
By SwiCago
#20696
burkmurray wrote:I've got this (mostly) working, using the new DNSserver library: https://github.com/esp8266/Arduino/tree/esp8266-sdk-1.0/hardware/esp8266com/esp8266/libraries/DNSServer

By default, the library only handles requests for a specified URL (e.g., example.com), but you can easily modify DNSServer.cpp to get you most of the way:

Code: Select all// Original
//    if (_dnsHeader->QR == DNS_QR_QUERY &&
//        _dnsHeader->OPCode == DNS_OPCODE_QUERY &&
//        requestIncludesOnlyOneQuestion() &&
//        getDomainNameWithoutWwwPrefix() == _domainName)

// Modified to remove domainName check - Works! - but doesnt handle domain subdirs
    if (_dnsHeader->QR == DNS_QR_QUERY &&
        _dnsHeader->OPCode == DNS_OPCODE_QUERY &&
        requestIncludesOnlyOneQuestion())


This will redirect any simple domain name (e.g., example.com, fu.bar, etc), but it doesn't handle a URL with a web page attached (e.g., example.com/examples) - or, rather, it redirects the domain and sends the page request to your server, which chokes on it.

I've asked the DNSServer library author to consider adding a captive portal function, and I'm hoping to have time later this week to play with it more - it seems like it ought to be easy to strip the page request.

Anyone have a suggestion for how to approach the problem?


I found that git yesterday and was playing with it...But didn't see if it would force any webpage request to the APs IP address. I would want any and all domains to be forced to the APs IP address and I see that your modification solves part of that.

Tawhiz20 wrote:I remember someone already solved your problem an posted on youtube : https://www.youtube.com/watch?v=fQM-GHY6VJ8
have a look...

GRTZ


Yeah, I found this and that guys blog posts and his git before I posted this question
https://github.com/reischle/CaptiveIntraweb
however it is written in LUA and not arduino code.

Here is his LAU code dns-liar.lua , maybe it is easy to convert to Arduino code. I'll play with it again tonight
Code: Select allsvr=net.createServer(net.UDP)
svr:on("receive",function(svr,pl)
decodedns(pl)
encodedns (query, transaction_id)
svr:send(response)
end)
svr:listen(53)

function decodedns(pl)
a=string.len(pl)
transaction_id  = string.sub(pl, 1, 2)
bte=""
query=""
i=13
bte2=""
while bte2 ~= "0" do
bte = string.byte(pl,i)
bte2 = string.format("%x", bte )
query = query .. string.char(bte)
i=i+1
end
end

function encodedns(query, transaction_id)
local tmpresponse=transaction_id
tmpresponse=tmpresponse .. unhex "81 80"
tmpresponse=tmpresponse .. unhex "00 01"
tmpresponse=tmpresponse .. unhex "00 01"
tmpresponse=tmpresponse .. unhex "00 00"
tmpresponse=tmpresponse .. unhex "00 00"
tmpresponse=tmpresponse .. query
tmpresponse=tmpresponse .. unhex "00 01"
tmpresponse=tmpresponse .. unhex "00 01"
tmpresponse=tmpresponse .. unhex "c0 0c"
tmpresponse=tmpresponse .. unhex "00 01"
tmpresponse=tmpresponse .. unhex "00 01"
tmpresponse=tmpresponse .. unhex "00 00"
tmpresponse=tmpresponse .. unhex "03 09"
tmpresponse=tmpresponse .. unhex "00 04"
--IP Address goes here
tmpresponse=tmpresponse .. unhex "c0 a8"
response=tmpresponse .. unhex "04 01"
collectgarbage("collect")
end

function unhex(str)
    str = string.gsub (str, "(%x%x) ?",
        function(h) return string.char(tonumber(h,16)) end)
       return str
end