Skip to content

Commit

Permalink
Added ability to see both JSON and Zone output.
Browse files Browse the repository at this point in the history
- Improved some styles, widened site a bit
- Added autofocus to input on home page
- Removed UncensoredDNS that was mistakenly added back since it doesn't support DNS over 53 (https://blog.uncensoreddns.org/blog/40-cleartext-dns-turned-off/)
  • Loading branch information
jclusso committed Feb 17, 2024
1 parent 3230d7c commit 88db55c
Show file tree
Hide file tree
Showing 12 changed files with 118 additions and 56 deletions.
4 changes: 2 additions & 2 deletions app/assets/stylesheets/application.tailwind.css
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

@layer components {
.btn {
@apply text-lg inline-block px-4 py-2 text-center bg-lime-500 text-black font-semibold rounded-lg transition cursor-pointer;
@apply text-lg inline-block px-4 py-2.5 text-center bg-lime-500 text-black font-semibold rounded-lg transition cursor-pointer;
@apply hover:bg-opacity-80 focus-visible:outline-lime-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2;
}

Expand All @@ -19,7 +19,7 @@
}

.form-field__input {
@apply text-lg font-medium bg-black rounded-md text-white border-neutral-800 transition;
@apply text-lg font-medium bg-black rounded-md text-white border-2 border-neutral-800 transition;
@apply focus-within:focus-within:ring-0 focus:border-neutral-400;
@apply placeholder:text-neutral-800;
}
Expand Down
4 changes: 2 additions & 2 deletions app/assets/stylesheets/code_theme.css
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pre code.hljs {
.hljs-template-variable,
.hljs-type,
.hljs-variable.language_ {
color: #ff7b72
@apply text-lime-500;
}

.hljs-title,
Expand Down Expand Up @@ -47,7 +47,7 @@ pre code.hljs {
.hljs-code,
.hljs-comment,
.hljs-formula {
color: #8b949e
@apply text-neutral-600;
}

.hljs-name,
Expand Down
2 changes: 2 additions & 0 deletions app/controllers/queries_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ def index
end

def show
@view = params[:view] || session[:last_query_view] || 'json'
session[:last_query_view] = @view
end

def create
Expand Down
3 changes: 3 additions & 0 deletions app/javascript/controllers/highlight_controller.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import { Controller } from "@hotwired/stimulus"
import hljs from 'highlight.js/lib/core';
import json from 'highlight.js/lib/languages/json';
import dns from 'highlight.js/lib/languages/dns';

export default class extends Controller {

connect() {
hljs.registerLanguage('json', json);
hljs.registerLanguage('dns', dns);
hljs.highlightAll();
this.element.classList.remove('opacity-0')
}

}
27 changes: 17 additions & 10 deletions app/lib/dns_lookup.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,24 @@ def run(domain, type)
response = resolver.query(domain, type)
@duration = (Time.monotonic_now - start_time) * 1000

hash = { status: response.rcode.to_s }
hash[:answer] = format_answer(response.answer) if response.answer.present?
hash.compact
rescue Dnsruby::NXDomain
{ status: 'NXDOMAIN' }
rescue Dnsruby::ServFail
{ status: 'SERVFAIL' }
{
json: {
status: response.rcode.to_s,
from: @server,
answer: (response.answer.present? ? format_answer(response.answer) : nil)
}.compact,
zone: response.to_s
}.compact
rescue Dnsruby::NXDomain => e
{ json: { status: 'NXDOMAIN', from: @server }, zone: e.response.to_s }
rescue Dnsruby::ServFail => e
{ json: { status: 'SERVFAIL', from: @server }, zone: e.response.to_s }
rescue Dnsruby::ResolvTimeout
{ status: 'TIMEOUT' }
rescue Dnsruby::NotImp
{ status: 'NOT IMPLEMENTED' }
{ json: { status: 'TIMEOUT', from: @server } }
rescue Dnsruby::NotImp => e
{ json: { status: 'NOTIMP', from: @server }, zone: e.response.to_s }
rescue Dnsruby::OtherResolvError
{ json: { status: 'OTHER ERROR', from: @server } }
end

private
Expand Down
1 change: 0 additions & 1 deletion app/models/query.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ def self.servers
'OpenNIC': '162.243.19.47',
'Yandex': '77.88.8.88',
'CleanBrowsing': '185.228.168.9',
'UncensoredDNS': '91.239.100.100',
'FreeDNS': '45.33.97.5',
'CyberGhost': '38.132.106.139',
'Neustar': '156.154.70.5',
Expand Down
2 changes: 1 addition & 1 deletion app/views/layouts/application.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
</head>

<body class="bg-neutral-950 text-white font-mono">
<main class="container mx-auto max-w-2xl p-4 sm:py-20">
<main class="container mx-auto max-w-3xl p-4 sm:py-20">
<div class="flex flex-col sm:justify-between items-center my-2">
<%= render_logo %>
<span class="text-sm text-neutral-400 p-3 font-semibold">A simple DNS lookup tool</span>
Expand Down
2 changes: 1 addition & 1 deletion app/views/queries/_form.html.erb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<%= form_with(model: Query.new(@query&.attributes), html: { class: 'grid gap-3' }) do |form| %>
<%= form.text_field :domain, label: false, placeholder: 'd53.co',
required: true, autocomplete: "off", autocorrect: "off",
autocapitalize: "off", spellcheck: "false" %>
autocapitalize: "off", spellcheck: "false", autofocus: @query&.domain.blank? %>
<div class="grid grid-cols-3 gap-3">
<%= form.select :type, Query.types, { selected: @query&.type || session[:last_query_type] },
{ class: 'form-field__input col-span-1' } %>
Expand Down
30 changes: 24 additions & 6 deletions app/views/queries/show.html.erb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<div class="space-y-8">
<%= render 'form' %>
<div class="grid grid-cols-2 sm:grid-cols-4 gap-3 bg-black p-4 rounded-lg sm:text-lg border border-neutral-800">
<div class="grid grid-cols-2 sm:grid-cols-4 gap-3 bg-black p-4 rounded-lg sm:text-lg border-2 border-neutral-800">
<div class="flex flex-col sm:col-span-3">
<span class="text-lime-500 font-semibold">Domain</span>
<span><%= @query.domain %></span>
Expand All @@ -18,15 +18,33 @@
<span><%= @query.duration_ms %></span>
</div>
</div>
<div class="bg-black p-4 rounded-lg sm:text-lg border border-neutral-800">
<%= turbo_frame_tag :results, class: "block bg-black p-4 rounded-lg sm:text-lg border-2 border-neutral-800 overflow-hidden" do %>
<%
def button_classes(button)
class_names(
"px-3 py-1 tracking-wider",
"bg-lime-500 text-black font-semibold" => @view == button,
"text-neutral-300 font-medium" => @view != button
)
end
%>
<div class="flex flex-col">
<div class="flex justify-between">
<div class="flex justify-between items-center">
<span class="text-lime-500 font-semibold">Results</span>
<span class="text-neutral-500">From <%= @query.server_ip %></span>
<% if @query.results.key?('json') && @query.results.key?('zone') %>
<div class="flex text-sm rounded-lg overflow-hidden border border-lime-500" data-turbo-prefetch="false">
<%= link_to 'JSON', query_path(@query, view: :json), class: button_classes('json') %>
<%= link_to 'ZONE', query_path(@query, view: :zone), class: button_classes('zone') %>
</div>
<% end %>
</div>
<pre data-controller="highlight" class="mt-1"><code class="language-json"><%= JSON.pretty_generate(@query.results) %></code></pre>
<% if @query.results.key?('zone') && @view == 'zone' %>
<pre data-controller="highlight" class="mt-1 opacity-0 transition"><code class="language-dns"><%= @query.results['zone'] %></code></pre>
<% else %>
<pre data-controller="highlight" class="mt-1 opacity-0 transition"><code class="language-json"><%= JSON.pretty_generate(@query.results['json'] || @query.results) %></code></pre>
<% end %>
</div>
</div>
<% end %>
</div>
<div class="flex p-4 text-xs text-neutral-600 justify-between">
<% if @query.session_id == session.id.to_s %>
Expand Down
1 change: 1 addition & 0 deletions config/importmap.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@
pin_all_from "app/javascript/controllers", under: "controllers"
pin "highlight.js/lib/core", to: "highlight.js--lib--core.js" # @11.9.0
pin "highlight.js/lib/languages/json", to: "highlight.js--lib--languages--json.js" # @11.9.0
pin "highlight.js/lib/languages/dns", to: "highlight.js--lib--languages--dns.js" # @11.9.0
95 changes: 62 additions & 33 deletions test/lib/dns_lookup_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,66 +3,81 @@
class DNSLookupTest < ActiveSupport::TestCase

def test_noerror
assert_equal 'NOERROR', dns_lookup.run('d53.co', 'A')[:status]
response = dns_lookup.run('d53.co', 'A')
assert_equal(
{ status: 'NOERROR', from: '1.1.1.1' }, response[:json].except(:answer)
)
assert_match 'NOERROR', response[:zone]
end

def test_servfail
assert_equal(
'SERVFAIL', dns_lookup.run('servfail.testing.d53.co', 'NS')[:status]
)
response = dns_lookup.run('servfail.testing.d53.co', 'NS')
assert_equal({ status: 'SERVFAIL', from: '1.1.1.1' }, response[:json])
assert_match 'SERVFAIL', response[:zone]
end

def test_timeout
assert_equal(
'TIMEOUT', dns_lookup.run('timeout.testing.d53.co', 'NS')[:status]
)
response = dns_lookup.run('timeout.testing.d53.co', 'NS')
assert_equal({ status: 'TIMEOUT', from: '1.1.1.1' }, response[:json])
assert_nil response[:zone]
end

def test_not_implemented
assert_equal('NOT IMPLEMENTED', dns_lookup.run('d53.co', 'ANY')[:status])
response = dns_lookup.run('d53.co', 'ANY')
assert_equal({ status: 'NOTIMP', from: '1.1.1.1' }, response[:json])
assert_match 'NOTIMP', response[:zone]
end


def test_a
assert_equal(
[{ type: 'A', address: '0.0.0.0' }],
get_answer('a.testing.d53.co', 'A')
)
response = get_answer('a.testing.d53.co', 'A')
assert_equal([{ type: 'A', address: '0.0.0.0' }], response[:json])
assert_match "a.testing.d53.co.\tIN\tA", response[:zone]
end

def test_aaaa
response = get_answer('aaaa.testing.d53.co', 'AAAA')
assert_equal(
[{ type: 'AAAA', address: '4149:8F20:F382:F7B2:45:1A0:A38F:34D9' }],
get_answer('aaaa.testing.d53.co', 'AAAA')
response[:json]
)
assert_match "aaaa.testing.d53.co.\tIN\tAAAA", response[:zone]
end

def test_caa
response = get_answer('caa.testing.d53.co', 'CAA')
assert_equal(
[{ type: 'CAA', flag: 0, property_tag: 'issue', property_value: 'd53.co' }],
get_answer('caa.testing.d53.co', 'CAA')
response[:json]
)
assert_match "caa.testing.d53.co.\tIN\tCAA", response[:zone]
end

def test_cert
response = get_answer('cert.testing.d53.co', 'CERT')
assert_equal(
[
{
type: 'CERT', algorithm: 'RSASHA256', cert: 'this-is-a-test-cert',
certtype: 'PKIX', keytag: 1
}
],
get_answer('cert.testing.d53.co', 'CERT')
response[:json]
)
assert_match "cert.testing.d53.co.\tIN\tCERT", response[:zone]
end

def test_cname
response = get_answer('cname.testing.d53.co', 'CNAME')
assert_equal(
[{ type: 'CNAME', name: 'cnamev.testing.d53.co' }],
get_answer('cname.testing.d53.co', 'CNAME')
response[:json]
)
assert_match "cname.testing.d53.co.\tIN\tCNAME", response[:zone]
end

def test_dnskey
response = get_answer('cloudflare.com', 'DNSKEY')
assert_equal(
[
{
Expand All @@ -76,11 +91,13 @@ def test_dnskey
key_tag: 2371, protocol: 3
}
],
get_answer('cloudflare.com', 'DNSKEY')
response[:json]
)
assert_match "cloudflare.com.\tIN\tDNSKEY", response[:zone]
end

def test_ds
response = get_answer('cloudflare.com', 'DS')
assert_equal(
[
{
Expand All @@ -89,49 +106,58 @@ def test_ds
digest_type: 'SHA-256', key_tag: 2371
}
],
get_answer('cloudflare.com', 'DS')
response[:json]
)
assert_match "cloudflare.com.\tIN\tDS", response[:zone]
end

def test_hinfo
response = DNSLookup.new('8.8.8.8').run('cloudflare.com', 'ANY')
assert_equal(
[{ type: 'HINFO', data: 'RFC8482' }],
remove_ttl(DNSLookup.new('8.8.8.8').run('cloudflare.com', 'ANY')[:answer])
remove_ttl(response.dig(:json, :answer))
)
assert_match "cloudflare.com.\tIN\tANY", response[:zone]
end

def test_mx
response = get_answer('mx.testing.d53.co', 'MX')
assert_equal(
[{ type: 'MX', exchange: 'mxv.testing.d53.co', preference: 0 }],
get_answer('mx.testing.d53.co', 'MX')
response[:json]
)
assert_match "mx.testing.d53.co.\tIN\tMX", response[:zone]
end

def test_ns
response = get_answer('d53.co', 'NS')
assert_equal(
[
{ type: 'NS', name: 'eva.ns.cloudflare.com' },
{ type: 'NS', name: 'sid.ns.cloudflare.com' }
],
get_answer('d53.co', 'NS')
response[:json]
)
assert_match "d53.co.\tIN\tNS", response[:zone]
end

def test_ptr_domain
response = get_answer('ptr.testing.d53.co', 'PTR')
assert_equal(
[{ type: 'PTR', name: 'ptrv.testing.d53.co' }],
get_answer('ptr.testing.d53.co', 'PTR')
response[:json]
)
assert_match "ptr.testing.d53.co.\tIN\tPTR", response[:zone]
end

def test_ptr_ip
assert_equal(
[{ type: 'PTR', name: 'dns.google' }],
get_answer('8.8.4.4', 'PTR')
)
response = get_answer('8.8.4.4', 'PTR')
assert_equal([{ type: 'PTR', name: 'dns.google' }], response[:json])
assert_match "4.4.8.8.in-addr.arpa.\tIN\tPTR", response[:zone]
end

def test_soa
response = get_answer('d53.co', 'SOA')
assert_equal(
[
{
Expand All @@ -140,22 +166,24 @@ def test_soa
rname: 'dns.cloudflare.com', serial: 2333549498
}
],
get_answer('d53.co', 'SOA')
response[:json]
)
assert_match "d53.co.\tIN\tSOA", response[:zone]
end

def test_txt
assert_equal(
[{ type: 'TXT', strings: ['test-text'] }],
get_answer('txt.testing.d53.co', 'TXT')
)
response = get_answer('txt.testing.d53.co', 'TXT')
assert_equal([{ type: 'TXT', strings: ['test-text'] }], response[:json])
assert_match "txt.testing.d53.co.\tIN\tTXT", response[:zone]
end

def test_uri
response = get_answer('uri.testing.d53.co', 'URI')
assert_equal(
[{ type: 'URI', priority: 0, target: 'uriv.testing.d53.co', weight: 0 }],
get_answer('uri.testing.d53.co', 'URI')
response[:json]
)
assert_match "uri.testing.d53.co.\tIN\tURI", response[:zone]
end

private
Expand All @@ -165,7 +193,8 @@ def dns_lookup
end

def get_answer(domain, type)
remove_ttl(dns_lookup.run(domain, type)[:answer])
response = dns_lookup.run(domain, type)
{ json: remove_ttl(response.dig(:json, :answer)), zone: response[:zone] }
end

def remove_ttl(fields)
Expand Down
3 changes: 3 additions & 0 deletions vendor/javascript/highlight.js--lib--languages--dns.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 88db55c

Please sign in to comment.