このコミットが含まれているのは:
+50
-8
@@ -1,18 +1,60 @@
|
||||
const puppeteer = require ('puppeteer')
|
||||
const fs = require ('fs')
|
||||
const dns = require ('dns').promises
|
||||
const net = require ('net')
|
||||
|
||||
const forbiddenNetworks = [
|
||||
['0.0.0.0', 8], ['10.0.0.0', 8], ['100.64.0.0', 10],
|
||||
['127.0.0.0', 8], ['169.254.0.0', 16], ['172.16.0.0', 12],
|
||||
['192.0.0.0', 24], ['192.0.2.0', 24], ['192.168.0.0', 16],
|
||||
['198.18.0.0', 15], ['198.51.100.0', 24], ['203.0.113.0', 24],
|
||||
['224.0.0.0', 4], ['240.0.0.0', 4], ['::', 128], ['::1', 128],
|
||||
['fc00::', 7], ['fe80::', 10], ['ff00::', 8], ['2001:db8::', 32],
|
||||
['::ffff:0:0', 96]]
|
||||
|
||||
const blockList = new net.BlockList ()
|
||||
forbiddenNetworks.forEach (([address, prefix]) => {
|
||||
blockList.addSubnet (address, prefix, net.isIPv6 (address) ? 'ipv6' : 'ipv4')
|
||||
})
|
||||
|
||||
|
||||
const safeUrl = async rawUrl => {
|
||||
const url = new URL (rawUrl)
|
||||
if (!['http:', 'https:'].includes (url.protocol) || url.username || url.password)
|
||||
return false
|
||||
|
||||
const addresses = await dns.lookup (url.hostname, { all: true, verbatim: true })
|
||||
return addresses.length > 0 && addresses.every (
|
||||
({ address, family }) => !blockList.check (address, family === 6 ? 'ipv6' : 'ipv4'))
|
||||
}
|
||||
|
||||
void (async () => {
|
||||
const url = process.argv[2]
|
||||
const output = process.argv[3]
|
||||
if (!(await safeUrl (url)))
|
||||
throw new Error ('Unsafe page URL')
|
||||
|
||||
const browser = await puppeteer.launch ({
|
||||
args: ['--no-sandbox', '--disable-setuid-sandbox'] })
|
||||
|
||||
const page = await browser.newPage ()
|
||||
await page.setViewport ({ width: 960, height: 960 })
|
||||
await page.goto (url, { waitUntil: 'networkidle2', timeout: 15000 })
|
||||
|
||||
await page.screenshot ({ path: output })
|
||||
await browser.close ()
|
||||
}) ()
|
||||
try
|
||||
{
|
||||
const page = await browser.newPage ()
|
||||
await page.setRequestInterception (true)
|
||||
page.on ('request', request => {
|
||||
void safeUrl (request.url ())
|
||||
.then (safe => safe ? request.continue () : request.abort ())
|
||||
.catch (() => request.abort ())
|
||||
})
|
||||
await page.setViewport ({ width: 960, height: 960 })
|
||||
await page.goto (url, { waitUntil: 'domcontentloaded', timeout: 12000 })
|
||||
await new Promise (resolve => setTimeout (resolve, 1000))
|
||||
await page.screenshot ({ path: output })
|
||||
}
|
||||
finally
|
||||
{
|
||||
await browser.close ()
|
||||
}
|
||||
}) ().catch (error => {
|
||||
console.error (error)
|
||||
process.exitCode = 1
|
||||
})
|
||||
|
||||
新しい課題から参照
ユーザをブロックする