Skip to content
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
f5da21c
added cdflag to `dig` and `multi-dig` command options
Dhravya Oct 3, 2022
71fd313
added cdflag to embeds
Dhravya Oct 3, 2022
d3dfe85
Updated README
Dhravya Oct 4, 2022
c6c7a60
Update src/utils/dig.js
Dhravya Oct 4, 2022
f9146dd
revert to old commit
Dhravya Oct 5, 2022
9d35753
Added cdflag bit again
Dhravya Oct 5, 2022
5f87fe5
wrangler config
Dhravya Oct 5, 2022
cb03cff
Update src/utils/dig.js
Dhravya Oct 5, 2022
aacfbf5
Update src/utils/dns.js
Dhravya Oct 5, 2022
5bc6df9
Update src/utils/dns.js
Dhravya Oct 5, 2022
80e984a
Update src/utils/dns.js
Dhravya Oct 5, 2022
4977121
Update src/utils/dns.js
Dhravya Oct 5, 2022
60df3d1
Update src/utils/dns.js
Dhravya Oct 5, 2022
43ea6da
Update src/utils/dig.js
Dhravya Oct 5, 2022
fbeefb0
undid the formatting
Dhravya Oct 5, 2022
7d6e9b8
import CHECKING_DISABLED
Dhravya Oct 5, 2022
c44ecde
Update src/utils/dns.js
Dhravya Oct 5, 2022
2e6802e
moved waring message to top of file
Dhravya Oct 5, 2022
b8d04b7
fixed eslint errors
Dhravya Oct 5, 2022
b45459c
Update src/utils/dig.js
Dhravya Oct 6, 2022
ee65c36
reverted wrangler.toml, max_length const, newlines in warning message
Dhravya Oct 6, 2022
97c2172
moved maxLength down
Dhravya Oct 6, 2022
4221d0e
Update src/utils/dns.js
Dhravya Oct 6, 2022
491d710
Update src/utils/dns.js
Dhravya Oct 6, 2022
22b5903
Update src/utils/dig.js
Dhravya Oct 6, 2022
33d1833
Update src/utils/dig.js
Dhravya Oct 6, 2022
949888c
Update src/utils/dig.js
Dhravya Oct 6, 2022
e38191d
Update src/utils/dig.js
Dhravya Oct 6, 2022
6ef55a3
Update src/utils/dig.js
Dhravya Oct 6, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,16 @@ Example:
/dig domain: cloudflare.com type: AAAA records short: True
```

### Disable DNSSEC checking

You can disable DNSSEC checking in the `dig` command by passing `cdflag` as true. This will get the records even if validation fails.

Example:

```txt
/dig domain: cloudflare.com type: AAAA records cdflag: True
```

### Refreshing existing results

You can refresh the DNS lookup results by clicking the Refresh button. Clicking it will trigger the bot to re-request the DNS query in the message, and update the results in the message. Any user can click this button.
Expand Down Expand Up @@ -185,6 +195,16 @@ Example:
/multi-dig domain: cloudflare.com types: CDS CDNSKEY short: True
```

### Disable DNSSEC checking

Exactly like `dig` command, you can disable dns checking by passing `cdflag` as true. This will get the records even if validation fails.

Example:

```txt
/multi-dig domain: cloudflare.com type: AAAA records cdflag: True
```

### Refreshing existing results

The `/multi-dig` command also provides a refresh button below each set of DNS results requested (or after each block of 10 DNS record types, if you requested more than 10).
Expand Down
9 changes: 8 additions & 1 deletion src/commands/dig.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ export default {
type: ApplicationCommandOptionType.Boolean,
required: false,
},
{
name: 'cdflag',
description: 'Disable DNSSEC checking',
type: ApplicationCommandOptionType.Boolean,
required: false,
},
{
name: 'provider',
description: 'DNS provider to use',
Expand All @@ -49,6 +55,7 @@ export default {
const rawDomain = ((interaction.data.options.find(opt => opt.name === 'domain') || {}).value || '').trim();
const rawType = ((interaction.data.options.find(opt => opt.name === 'type') || {}).value || '').trim();
const rawShort = (interaction.data.options.find(opt => opt.name === 'short') || {}).value || false;
const rawCdFlag = (interaction.data.options.find(opt => opt.name === 'cdflag') || {}).value || false;
const rawProvider = ((interaction.data.options.find(opt => opt.name === 'provider') || {}).value || '').trim();

// Parse domain input, return any error response
Expand All @@ -64,7 +71,7 @@ export default {
// Do the processing after acknowledging the Discord command
wait((async () => {
// Run dig and get the embeds
const [ embed ] = await handleDig({ domain, types: [ type ], short: rawShort, provider });
const [ embed ] = await handleDig({ domain, types: [ type ], short: rawShort, cdflag: rawCdFlag, provider });

// Edit the original deferred response
await editDeferred(interaction, {
Expand Down
9 changes: 8 additions & 1 deletion src/commands/multi-dig.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ export default {
type: ApplicationCommandOptionType.Boolean,
required: false,
},
{
name: 'cdflag',
description: 'Disable DNSSEC checking',
type: ApplicationCommandOptionType.Boolean,
required: false,
},
{
name: 'provider',
description: 'DNS provider to use',
Expand All @@ -44,6 +50,7 @@ export default {
const rawDomain = ((interaction.data.options.find(opt => opt.name === 'domain') || {}).value || '').trim();
const rawTypes = ((interaction.data.options.find(opt => opt.name === 'types') || {}).value || '').trim();
const rawShort = (interaction.data.options.find(opt => opt.name === 'short') || {}).value || false;
const rawCdFlag = (interaction.data.options.find(opt => opt.name === 'cdflag') || {}).value || false;
const rawProvider = ((interaction.data.options.find(opt => opt.name === 'provider') || {}).value || '').trim();

// Parse domain input, return any error response
Expand All @@ -68,7 +75,7 @@ export default {
// Do the processing after acknowledging the Discord command
wait((async () => {
// Run dig and get the embeds
const embeds = await handleDig({ domain, types, short: rawShort, provider });
const embeds = await handleDig({ domain, types, short: rawShort, cdflag: rawCdFlag, provider });

// Edit the original deferred response with the first 10 embeds
const messageBase = {
Expand Down
1 change: 1 addition & 0 deletions src/components/dig-provider.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export default {
domain: embeds[0].name,
types: embeds.map(data => data.type),
short: embeds[0].short,
cdflag: embeds[0].cdflag,
provider,
});

Expand Down
1 change: 1 addition & 0 deletions src/components/dig-refresh.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export default {
domain: embeds[0].name,
types: embeds.map(data => data.type),
short: embeds[0].short,
cdflag: embeds[0].cdflag,
provider: embeds[0].provider,
});

Expand Down
21 changes: 14 additions & 7 deletions src/utils/dig.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import providers from './providers.js';
import { presentTable } from './table.js';
import { createEmbed } from './embed.js';

const DNSSEC_DISABLED_WARNING_MESSAGE = '\n\n:warning: cd bit set for request, DNSSEC validation disabled';

export const validateDomain = (input, response) => {
// Clean the input
const cleaned = input
Expand All @@ -28,23 +30,27 @@ export const validateDomain = (input, response) => {
};
};

export const handleDig = async ({ domain, types, short, provider }) => {
export const handleDig = async ({ domain, types, short, cdflag, provider }) => {
// Make the DNS queries
const results = await Promise.all(types.map(type =>
performLookupWithCache(domain, type, provider.doh).then(data => ({ type, data }))));
performLookupWithCache(domain, type, provider.doh, cdflag).then(data => ({ type, data }))));

const max_length = 4096 - (cdflag ? DNSSEC_DISABLED_WARNING_MESSAGE.length : 0);

// Define the presenter
const present = (type, data) => {
// Generate the dig command equivalent
const digCmd = `\`${data.name} ${type} @${provider.dig} +noall +answer${short ? ' +short' : ''}\`\n`;
const digCmd = `\`${data.name} ${type} @${provider.dig} +noall +answer${short ? ' +short' : ''}${cdflag ? ' +cdflag' : ''}\`\n`;

// Error message
if (typeof data === 'object' && data.message)
return `${digCmd}\n${data.message}`;

// No results
if (typeof data !== 'object' || !Array.isArray(data.answer) || data.answer.length === 0)
return `${digCmd}\nNo records found`;
return `${digCmd}\nNo records found${(cdflag
? DNSSEC_DISABLED_WARNING_MESSAGE
: '')}`;

// Map the data if short requested
const sourceRows = short ? data.answer.map(x => x.data) : data.answer;
Expand All @@ -63,12 +69,12 @@ export const handleDig = async ({ domain, types, short, provider }) => {

// Keep adding rows until we reach Discord 4096 char limit
for (const row of sourceRows) {
if (output([...finalRows, row]).length > 4096) break;
if (output([...finalRows, row]).length > max_length) break;
finalRows.push(row);
}

// Render and return final rows
return output(finalRows);
return output(finalRows) + (cdflag ? DNSSEC_DISABLED_WARNING_MESSAGE : '');
};

// Convert results to an embed
Expand All @@ -77,7 +83,7 @@ export const handleDig = async ({ domain, types, short, provider }) => {

export const parseEmbed = embed => {
// Match the domain name, type and if the short format was requested
const descMatch = embed.description.match(/^`(\S+) (\S+) @(\S+) \+noall \+answer( \+short)?`\n/);
const descMatch = embed.description.match(/^`(\S+) (\S+) @(\S+) \+noall \+answer( \+short)?( \+cdflag)?`\n/);
if (!descMatch) return null;

// Check the type
Expand All @@ -92,6 +98,7 @@ export const parseEmbed = embed => {
name: descMatch[1],
type: descMatch[2],
short: !!descMatch[4],
cdflag: descMatch[5],
provider,
};
};
45 changes: 25 additions & 20 deletions src/utils/dns.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Buffer } from 'buffer';
import { decode, encode, RECURSION_DESIRED } from 'dns-packet';
import { decode, encode, RECURSION_DESIRED, CHECKING_DISABLED } from 'dns-packet';
import { toRcode } from 'dns-packet/rcodes.js';
import fetch from 'node-fetch';
import cache from './cache.js';
Expand Down Expand Up @@ -74,11 +74,12 @@ const processAnswer = (type, answer) => {
return answer;
};

const performLookupJson = async (domain, type, endpoint) => {
const performLookupJson = async (domain, type, endpoint, cdflag) => {
// Build the query URL
const query = new URL(endpoint.endpoint);
query.searchParams.set('name', domain);
query.searchParams.set('type', type.toLowerCase());
query.searchParams.set('cd', cdflag);

// Make our request
return fetch(query.href, {
Expand All @@ -90,12 +91,12 @@ const performLookupJson = async (domain, type, endpoint) => {

const randInt = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;

const performLookupDns = async (domain, type, endpoint) => {
const performLookupDns = async (domain, type, endpoint, cdflag) => {
// Build the query packet
const packet = encode({
type: 'query',
id: randInt(1, 65534),
flags: RECURSION_DESIRED,
flags: RECURSION_DESIRED | (cdflag ? CHECKING_DISABLED : 0),
questions: [ {
name: domain,
type,
Expand All @@ -111,30 +112,34 @@ const performLookupDns = async (domain, type, endpoint) => {
headers: {
Accept: 'application/dns-message',
},
}).then(res => res.arrayBuffer()).then(data => {
const dec = decode(Buffer.from(data));
return {
Status: toRcode(dec.rcode),
Question: dec.questions,
Answer: dec.answers,
};
});
})
.then(res => res.arrayBuffer())
.then(data => {
const dec = decode(Buffer.from(data));
return {
Status: toRcode(dec.rcode),
Question: dec.questions,
Answer: dec.answers,
};
});
};

const performLookupRequest = async (domain, type, endpoint) => {
const performLookupRequest = async (domain, type, endpoint, cdflag) => {
switch (endpoint.type) {
case 'json':
return performLookupJson(domain, type, endpoint);
return performLookupJson(domain, type, endpoint, cdflag);
case 'dns':
return performLookupDns(domain, type, endpoint);
return performLookupDns(domain, type, endpoint, cdflag);
default:
return Promise.reject(new Error(`Unknown endpoint type: ${endpoint.type}`));
return Promise.reject(
new Error(`Unknown endpoint type: ${endpoint.type}`),
);
}
};

const performLookup = async (domain, type, endpoint) => {
const performLookup = async (domain, type, endpoint, cdflag) => {
// Make the request
const { Status, Question, Answer } = await performLookupRequest(domain, type, endpoint);
const { Status, Question, Answer } = await performLookupRequest(domain, type, endpoint, cdflag);

// Return an error message for non-zero status
if (Status !== 0)
Expand All @@ -150,9 +155,9 @@ const performLookup = async (domain, type, endpoint) => {
};
};

export const performLookupWithCache = (domain, type, endpoint) => cache(
export const performLookupWithCache = (domain, type, endpoint, cdflag) => cache(
performLookup,
[ domain, type, endpoint ],
[ domain, type, endpoint, cdflag ],
`dns-${domain}-${type}-${endpoint.endpoint}`,
Number(process.env.CACHE_DNS_TTL) || 10,
);
Expand Down