mirror of
https://github.com/NginxProxyManager/nginx-proxy-manager.git
synced 2025-04-29 18:42:28 +00:00
Merge 05c4c0470eceecf6ee231a8990d552c640de50c4 into 63d06da8a8591e7a9b2a1873eb91ce1c42b2b0f9
This commit is contained in:
commit
06f721bd54
90
backend/internal/PiHoleDNSPlugin.js
Normal file
90
backend/internal/PiHoleDNSPlugin.js
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
const axios = require('axios');
|
||||||
|
const cheerio = require('cheerio');
|
||||||
|
const qs = require('querystring');
|
||||||
|
|
||||||
|
const PIHOLE_PLUGIN_ENABLED = process.env.PIHOLE_PLUGIN_ENABLED === 'true';
|
||||||
|
const PIHOLE_PASSWORD = process.env.PIHOLE_PASSWORD;
|
||||||
|
const PIHOLE_LOGIN_URL = 'http://'+process.env.PIHOLE_IP+'/admin/index.php';
|
||||||
|
const PIHOLE_CUSTOMDNS_URL = 'http://'+process.env.PIHOLE_IP+'/admin/scripts/pi-hole/php/customdns.php';
|
||||||
|
|
||||||
|
// IP to entry in pihole dns table
|
||||||
|
const DNS_TABLE_IP = process.env.DNS_TABLE_IP;
|
||||||
|
|
||||||
|
// Function to update Pi-hole with domain and IP
|
||||||
|
async function updatePihole(domain, action) {
|
||||||
|
// Check if the Pi-hole plugin is enabled
|
||||||
|
if (!PIHOLE_PLUGIN_ENABLED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// Step 1: Login to Pi-hole to get session cookie
|
||||||
|
const loginResponse = await axios.post(PIHOLE_LOGIN_URL, qs.stringify({
|
||||||
|
pw: PIHOLE_PASSWORD,
|
||||||
|
}), {
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
|
'User-Agent': 'Mozilla/5.0' // Pretend to be a browser
|
||||||
|
},
|
||||||
|
withCredentials: true // Send cookies with the request
|
||||||
|
});
|
||||||
|
|
||||||
|
if (loginResponse.status === 200) {
|
||||||
|
// Extract session cookie (PHPSESSID)
|
||||||
|
const cookies = loginResponse.headers['set-cookie'];
|
||||||
|
const sessionCookie = cookies.find((cookie) => cookie.startsWith('PHPSESSID'));
|
||||||
|
|
||||||
|
if (!sessionCookie) {
|
||||||
|
throw new Error('PHP session cookie not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 2: Fetch HTML content of index.php after login
|
||||||
|
const indexHtmlResponse = await axios.get(PIHOLE_LOGIN_URL, {
|
||||||
|
headers: {
|
||||||
|
Cookie: sessionCookie.split(';')[0] // Send only the PHPSESSID part of the cookie
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Load HTML content into cheerio for DOM manipulation
|
||||||
|
const $ = cheerio.load(indexHtmlResponse.data);
|
||||||
|
|
||||||
|
// Extract token value from element with ID "token"
|
||||||
|
const token = $('#token').text().trim();
|
||||||
|
|
||||||
|
|
||||||
|
// Step 3: Add custom DNS record with explicit session cookie and token
|
||||||
|
const headers = {
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
||||||
|
'Pragma': 'no-cache',
|
||||||
|
'Accept': 'application/json, text/javascript, */*; q=0.01',
|
||||||
|
'Accept-Language': 'en-GB,en;q=0.9',
|
||||||
|
'Accept-Encoding': 'gzip, deflate',
|
||||||
|
'Connection': 'keep-alive',
|
||||||
|
'X-Requested-With': 'XMLHttpRequest',
|
||||||
|
'Cookie': sessionCookie.split(';')[0] // Send only the PHPSESSID part of the cookie
|
||||||
|
};
|
||||||
|
|
||||||
|
// Request data including token
|
||||||
|
const requestData = {
|
||||||
|
action: action,
|
||||||
|
ip: DNS_TABLE_IP,
|
||||||
|
domain: domain,
|
||||||
|
token: token // Use the token retrieved from the HTML page
|
||||||
|
};
|
||||||
|
|
||||||
|
// Make the POST request to add custom DNS record
|
||||||
|
const addRecordResponse = await axios.post(PIHOLE_CUSTOMDNS_URL, qs.stringify(requestData), {
|
||||||
|
headers: headers
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('PiHole API:', addRecordResponse.data);
|
||||||
|
} else {
|
||||||
|
console.error('Login failed:', loginResponse.statusText);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error logging in or adding custom DNS record:', error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
updatePihole: updatePihole
|
||||||
|
};
|
@ -6,6 +6,7 @@ const internalHost = require('./host');
|
|||||||
const internalNginx = require('./nginx');
|
const internalNginx = require('./nginx');
|
||||||
const internalAuditLog = require('./audit-log');
|
const internalAuditLog = require('./audit-log');
|
||||||
const internalCertificate = require('./certificate');
|
const internalCertificate = require('./certificate');
|
||||||
|
const piHole = require('./PiHoleDNSPlugin');
|
||||||
|
|
||||||
function omissions () {
|
function omissions () {
|
||||||
return ['is_deleted'];
|
return ['is_deleted'];
|
||||||
@ -64,9 +65,21 @@ const internalProxyHost = {
|
|||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
|
||||||
|
// Update PiHole
|
||||||
|
for (let i = 0; i < row.domain_names.length; i++) {
|
||||||
|
piHole.updatePihole(row.domain_names[i], 'add').then();
|
||||||
|
}
|
||||||
|
|
||||||
return row;
|
return row;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
// Update PiHole
|
||||||
|
for (let i = 0; i < row.domain_names.length; i++) {
|
||||||
|
piHole.updatePihole(row.domain_names[i], 'add').then();
|
||||||
|
}
|
||||||
|
|
||||||
return row;
|
return row;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -153,9 +166,18 @@ const internalProxyHost = {
|
|||||||
data.certificate_id = cert.id;
|
data.certificate_id = cert.id;
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
// Update PiHole
|
||||||
|
for (let i = 0; i < row.domain_names.length; i++) {
|
||||||
|
piHole.updatePihole(row.domain_names[i], 'delete').then();
|
||||||
|
}
|
||||||
return row;
|
return row;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
// Update PiHole
|
||||||
|
for (let i = 0; i < row.domain_names.length; i++) {
|
||||||
|
piHole.updatePihole(row.domain_names[i], 'delete').then();
|
||||||
|
|
||||||
|
}
|
||||||
return row;
|
return row;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -181,6 +203,7 @@ const internalProxyHost = {
|
|||||||
meta: data
|
meta: data
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
|
||||||
return saved_row;
|
return saved_row;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -200,6 +223,9 @@ const internalProxyHost = {
|
|||||||
.then((new_meta) => {
|
.then((new_meta) => {
|
||||||
row.meta = new_meta;
|
row.meta = new_meta;
|
||||||
row = internalHost.cleanRowCertificateMeta(row);
|
row = internalHost.cleanRowCertificateMeta(row);
|
||||||
|
for (let i = 0; i < row.domain_names.length; i++) {
|
||||||
|
piHole.updatePihole(row.domain_names[i], 'add').then();
|
||||||
|
}
|
||||||
return _.omit(row, omissions());
|
return _.omit(row, omissions());
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -275,6 +301,11 @@ const internalProxyHost = {
|
|||||||
is_deleted: 1
|
is_deleted: 1
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
// Update PiHole
|
||||||
|
|
||||||
|
for (let i = 0; i < row.domain_names.length; i++) {
|
||||||
|
piHole.updatePihole(row.domain_names[i], 'delete').then();
|
||||||
|
}
|
||||||
// Delete Nginx Config
|
// Delete Nginx Config
|
||||||
return internalNginx.deleteConfig('proxy_host', row)
|
return internalNginx.deleteConfig('proxy_host', row)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
@ -6,9 +6,11 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ajv": "^6.12.0",
|
"ajv": "^6.12.0",
|
||||||
"archiver": "^5.3.0",
|
"archiver": "^5.3.0",
|
||||||
|
"axios": "^1.7.2",
|
||||||
"batchflow": "^0.4.0",
|
"batchflow": "^0.4.0",
|
||||||
"bcrypt": "^5.0.0",
|
"bcrypt": "^5.0.0",
|
||||||
"body-parser": "^1.19.0",
|
"body-parser": "^1.19.0",
|
||||||
|
"cheerio": "^1.0.0-rc.12",
|
||||||
"compression": "^1.7.4",
|
"compression": "^1.7.4",
|
||||||
"express": "^4.19.2",
|
"express": "^4.19.2",
|
||||||
"express-fileupload": "^1.1.9",
|
"express-fileupload": "^1.1.9",
|
||||||
|
@ -29,6 +29,12 @@ services:
|
|||||||
DB_MYSQL_NAME: 'npm'
|
DB_MYSQL_NAME: 'npm'
|
||||||
# DB_SQLITE_FILE: "/data/database.sqlite"
|
# DB_SQLITE_FILE: "/data/database.sqlite"
|
||||||
# DISABLE_IPV6: "true"
|
# DISABLE_IPV6: "true"
|
||||||
|
# pihole:
|
||||||
|
# DNS_TABLE_IP: '192.168.10.10'
|
||||||
|
# PIHOLE_PLUGIN_ENABLED: 'true'
|
||||||
|
# PIHOLE_PASSWORD: 'password'
|
||||||
|
# PIHOLE_IP: '192.168.10.2'
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
- npm_data:/data
|
- npm_data:/data
|
||||||
- le_data:/etc/letsencrypt
|
- le_data:/etc/letsencrypt
|
||||||
|
Loading…
x
Reference in New Issue
Block a user