mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2026-07-07 18:01:42 +00:00
fix: correct NAT64 embedded IPv4 extraction
NAT64 addresses encode the IPv4 in the last 32 bits as two 16-bit hex groups, not dotted-decimal. Extract properly and validate the embedded IPv4 is not private. Signed-off-by: Arunesh Dwivedi <arunesh.devops@gmail.com>
This commit is contained in:
parent
53c1e851ab
commit
cdae28c848
1 changed files with 22 additions and 5 deletions
|
|
@ -95,21 +95,38 @@ class Server {
|
|||
const ssrfFilterLib = require('ssrf-req-filter')
|
||||
const net = require('net')
|
||||
const ipaddr = require('ipaddr.js')
|
||||
// Check if an IPv4 address string is private/reserved
|
||||
function isPrivateIPv4(ip) {
|
||||
try {
|
||||
const addr = ipaddr.IPv4.parse(ip)
|
||||
return addr.range() !== 'unicast'
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
global.getSsrfFilter = (url) => {
|
||||
const agent = ssrfFilterLib(url)
|
||||
const originalCreateConnection = agent.createConnection.bind(agent)
|
||||
agent.createConnection = function(options, callback) {
|
||||
const { host: address } = options
|
||||
// Allow NAT64 addresses (64:ff9b::/96 prefix) but validate embedded IPv4
|
||||
if (address && address.startsWith('64:ff9b::')) {
|
||||
try {
|
||||
const addr = ipaddr.parse(address)
|
||||
if (addr.kind() === 'ipv6') {
|
||||
// Extract the embedded IPv4 from the last 32 bits of the NAT64 address
|
||||
// NAT64 format: 64:ff9b::[96-bit prefix][32-bit IPv4]
|
||||
// The IPv4 is encoded as two 16-bit hex groups in the last two positions
|
||||
const parts = addr.toNormalizedString().split(':')
|
||||
const lastPart = parts[parts.length - 1]
|
||||
if (lastPart && lastPart.includes('.')) {
|
||||
const ipv4Addr = ipaddr.parse(lastPart)
|
||||
if (ipv4Addr.range() !== 'unicast') {
|
||||
throw new Error('NAT64 embeds non-unicast IPv4')
|
||||
if (parts.length >= 2) {
|
||||
// Last two 16-bit groups contain the 32-bit IPv4
|
||||
const high = parseInt(parts[parts.length - 2], 16)
|
||||
const low = parseInt(parts[parts.length - 1], 16)
|
||||
if (!isNaN(high) && !isNaN(low)) {
|
||||
const ipv4 = `${(high >> 8) & 0xff}.${high & 0xff}.${(low >> 8) & 0xff}.${low & 0xff}`
|
||||
if (isPrivateIPv4(ipv4)) {
|
||||
throw new Error(`NAT64 address embeds private IPv4: ${ipv4}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue