proxy-bridge: add keyring-based HTTP CONNECT proxy bridge
This commit is contained in:
@@ -0,0 +1,57 @@
|
|||||||
|
const http = require('http');
|
||||||
|
const net = require('net');
|
||||||
|
const { execSync } = require('child_process');
|
||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
|
// 1. CONFIGURATION
|
||||||
|
const PROXY_HOST = 'PROXY_HOST_PLACEHOLDER';
|
||||||
|
const PROXY_PORT = 8080;
|
||||||
|
|
||||||
|
// 2. FETCH SECRETS FROM KEYRING
|
||||||
|
let USER, PASS;
|
||||||
|
try {
|
||||||
|
// Read the username we saved during setup
|
||||||
|
USER = JSON.parse(fs.readFileSync('/opt/proxy-bridge/user.json')).username;
|
||||||
|
// Query the Ubuntu Keyring for the password associated with this user/service
|
||||||
|
PASS = execSync(`secret-tool lookup service proxy-bridge account ${USER}`).toString().trim();
|
||||||
|
|
||||||
|
if (!PASS) throw new Error("Password returned empty.");
|
||||||
|
} catch (e) {
|
||||||
|
console.error("CRITICAL: Could not retrieve credentials from keyring. Did you run setup.js?");
|
||||||
|
console.error(e.message);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. GENERATE AUTH
|
||||||
|
const AUTH_HEADER = 'Basic ' + Buffer.from(`${USER}:${PASS}`).toString('base64');
|
||||||
|
|
||||||
|
const server = http.createServer();
|
||||||
|
|
||||||
|
server.on('connect', (req, clientSocket, head) => {
|
||||||
|
console.log(`--> Connecting to ${req.url}`);
|
||||||
|
|
||||||
|
const serverSocket = net.connect(PROXY_PORT, PROXY_HOST, () => {
|
||||||
|
serverSocket.write(`CONNECT ${req.url} HTTP/1.1\r\n` +
|
||||||
|
`Host: ${req.url}\r\n` +
|
||||||
|
`Proxy-Authorization: ${AUTH_HEADER}\r\n` +
|
||||||
|
`Proxy-Connection: Keep-Alive\r\n\r\n`);
|
||||||
|
serverSocket.write(head);
|
||||||
|
});
|
||||||
|
|
||||||
|
serverSocket.once('data', (data) => {
|
||||||
|
if (data.toString().includes('200')) {
|
||||||
|
clientSocket.write('HTTP/1.1 200 Connection Established\r\n\r\n');
|
||||||
|
serverSocket.pipe(clientSocket);
|
||||||
|
clientSocket.pipe(serverSocket);
|
||||||
|
} else {
|
||||||
|
clientSocket.write(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
serverSocket.on('error', () => clientSocket.end());
|
||||||
|
clientSocket.on('error', () => serverSocket.end());
|
||||||
|
});
|
||||||
|
|
||||||
|
server.listen(8888, '127.0.0.1', () => {
|
||||||
|
console.log('Bridge active on http://127.0.0.1:8888 (Auth via Keyring)');
|
||||||
|
});
|
||||||
Executable
+70
@@ -0,0 +1,70 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Ensure the script is NOT run as root, so the user-level systemd service configures correctly
|
||||||
|
if [ "$EUID" -eq 0 ]; then
|
||||||
|
echo "❌ Please run this script as your standard user, not as root."
|
||||||
|
echo "The script will prompt for sudo access automatically when needed."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "=== Proxy Bridge Installer ==="
|
||||||
|
|
||||||
|
# 1. Verify files exist
|
||||||
|
if [ ! -f "bridge.js" ] || [ ! -f "setup.js" ]; then
|
||||||
|
echo "❌ Error: bridge.js and/or setup.js not found in the current directory."
|
||||||
|
echo "Please place this script in the same folder as your Node.js scripts."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 2. Install dependencies (requires sudo)
|
||||||
|
echo "--> Installing required system packages (libsecret-tools)..."
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y libsecret-tools
|
||||||
|
|
||||||
|
# 3. Setup application directory (requires sudo)
|
||||||
|
echo "--> Creating /opt/proxy-bridge directory..."
|
||||||
|
sudo mkdir -p /opt/proxy-bridge
|
||||||
|
sudo chown -R $USER:$USER /opt/proxy-bridge
|
||||||
|
|
||||||
|
# 4. Copy files
|
||||||
|
echo "--> Copying scripts to /opt/proxy-bridge..."
|
||||||
|
cp bridge.js /opt/proxy-bridge/
|
||||||
|
cp setup.js /opt/proxy-bridge/
|
||||||
|
|
||||||
|
# 5. Setup User-Level systemd Service
|
||||||
|
echo "--> Configuring user-level systemd service..."
|
||||||
|
mkdir -p ~/.config/systemd/user/
|
||||||
|
|
||||||
|
cat <<EOF > ~/.config/systemd/user/proxy-bridge.service
|
||||||
|
[Unit]
|
||||||
|
Description=Dumb Pipe Proxy Bridge (Keyring Auth)
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
ExecStart=/usr/bin/node /opt/proxy-bridge/bridge.js
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=5
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=default.target
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# 6. Enable the service
|
||||||
|
echo "--> Reloading systemd and enabling service..."
|
||||||
|
systemctl --user daemon-reload
|
||||||
|
systemctl --user enable proxy-bridge.service
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "✅ Installation Complete!"
|
||||||
|
echo "=================================================="
|
||||||
|
echo "Next Steps:"
|
||||||
|
echo "1. Run the interactive setup to store your proxy credentials:"
|
||||||
|
echo " node /opt/proxy-bridge/setup.js"
|
||||||
|
echo ""
|
||||||
|
echo "2. Start the background service:"
|
||||||
|
echo " systemctl --user start proxy-bridge.service"
|
||||||
|
echo ""
|
||||||
|
echo "3. Check the logs to ensure it's running smoothly:"
|
||||||
|
echo " journalctl --user -u proxy-bridge.service -f"
|
||||||
|
echo "=================================================="
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
const readline = require('readline');
|
||||||
|
const { execSync } = require('child_process');
|
||||||
|
|
||||||
|
const rl = readline.createInterface({
|
||||||
|
input: process.stdin,
|
||||||
|
output: process.stdout
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("=== Proxy Bridge Keyring Setup ===");
|
||||||
|
|
||||||
|
rl.question('Enter your corporate username: ', (user) => {
|
||||||
|
rl.question('Enter your corporate password: ', (pass) => {
|
||||||
|
try {
|
||||||
|
// Securely store the password in the Ubuntu Keyring using secret-tool
|
||||||
|
// We use standard input to pass the password so it doesn't appear in process lists
|
||||||
|
execSync(`secret-tool store --label="Proxy Bridge Credentials" service proxy-bridge account ${user}`, {
|
||||||
|
input: pass
|
||||||
|
});
|
||||||
|
|
||||||
|
// Store the username in a local config just so the bridge knows WHICH account to look up
|
||||||
|
require('fs').writeFileSync('/opt/proxy-bridge/user.json', JSON.stringify({ username: user }));
|
||||||
|
|
||||||
|
console.log("\n✅ Credentials successfully stored in the system keyring.");
|
||||||
|
} catch (error) {
|
||||||
|
console.error("\n❌ Failed to store credentials in keyring:", error.message);
|
||||||
|
}
|
||||||
|
rl.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Hide typing for password (basic implementation)
|
||||||
|
rl._writeToOutput = function _writeToOutput(stringToWrite) {
|
||||||
|
if (rl.history.length === 0) rl.output.write("*");
|
||||||
|
};
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user