My Journey (with guides and code)

Thank you for this long inputs friend. And best of luck for your journey.

I'm not a programmer, but i hope to setup my own 4G proxies network (rotating on each request for my visit bot) for my personal use someday.

Can you tell me how many IP's can you generate and rotate with this proxy farm?
The amount of IPs depends on your exact location.
 
  • Like
Reactions: C63
Is there any rough number you can tell with one dongle how many IP's can generate?

Disable WiFi in your phone, check your phones IP. Activate and then deactivate airplane mode, check your IP again. Do this a few times to get a feeling. There really is no way to know unless you have a SIM and try, which is why I’m mainly looking at plans I can cancel on a monthly basis rn.

Usually with an IP of x.x.y.z if only the z part changes that means you should have access to 256 IPs in the same subnet. If the y part changes, each y should give you 256 IPs based on the z.

Practical example: I found a carrier I really liked for the price, flexibility and online interface BUT in testing, the IP only ever changes when I disconnect it >30 minutes, so that’s not sufficient. Checking my phones plan/SIM (which is a bit more expensive so not the best for a proxy) like above revealed I get 4 different y‘s, so about 256x4=1024 IPs in total. Now I’m shopping around for good deals and to check different carriers, but will also do the phone check when being out on the weekend to get a feeling for my current carrier (cause 1000 IPs at home is a nice start but not that many)
 
  • Like
Reactions: C63
Disable WiFi in your phone, check your phones IP. Activate and then deactivate airplane mode, check your IP again. Do this a few times to get a feeling.

Usually with an IP of x.x.y.z if only the z part changes that means you should have access to 256 IPs in the same subnet. If the y part changes, each y should give you 256 IPs based on the z.

Practical example: I found a carrier I really liked for the price, flexibility and online interface BUT in testing, the IP only ever changes when I disconnect it >30 minutes, so that’s not sufficient. Checking my phones plan/SIM (which is a bit more expensive so not the best for a proxy) like above revealed I get 4 different y‘s, so about 256x4=1024 IPs in total. Now I’m shopping around for good deals and to check different carriers, but will also do the phone check when being out on the weekend to get a feeling for my current carrier (cause 1000 IPs at home is a nice start but not that many)

I have a collect a list last year using connect and disconnect method. I got more than 200 IP's from one sim card/ one mobile network in my country. and there other GSM network (5 companies) available in my country.

So that part I did manually. I want to learn how to do that automatically for each request and rotating. I just need that mechanism dear. That's the hard part, and the thread owner doing that nicely with using dongle farm.
 
I have a collect a list last year using connect and disconnect method. I got more than 200 IP's from one sim card/ one mobile network in my country. and there other GSM network (5 companies) available in my country.

So that part I did manually. I want to learn how to do that automatically for each request and rotating. I just need that mechanism dear. That's the hard part, and the thread owner doing that nicely with using dongle farm.

This is where the x.x.y.z format comes in, if the first two x are very unlikely to vary in my limited experience and then for every y it’s pretty safe to assume 256 z, so that gives you an estimate. Reconnecting about 10-20 times was enough for me to assume 1000 IPs. But you can also try and track the IPs in a file/database upon changing, I might be able to code a barebones solution on the weekend if I find an hour of time, but no promises
 
  • Like
Reactions: C63
This is where the x.x.y.z format comes in, if the first two x are very unlikely to vary in my limited experience and then for every y it’s pretty safe to assume 256 z, so that gives you an estimate. Reconnecting about 10-20 times was enough for me to assume 1000 IPs. But you can also try and track the IPs in a file/database upon changing, I might be able to code a barebones solution on the weekend if I find an hour of time, but no promises

And brother once I saw a news some people did a phone farm as well using old phones (smart mobile), they did phone farms.
 
Guys, try this: turn on cellular data and then open whatsmyip site or whatever.
Remember your IP.

Then turn on Flight mode for 5 seconds or so..
Then turn it off.

Refresh the whatsmyip page. You will get new IP.
Reading this thread made me curious about IP change.
And I saw from some automation thread on BHW that the guy turned on/off Flight mode and got fresh IP.

Im not sure how many rotations I can have but mostly it changes whole IP.
Then sometimes just last 6 digits xxx.xxx.128.128
The xxx.xxx part stays same.
But not always.

Of course this is just my tests and the results may vary.
Im in EU with my common SIM provider I used for years.
 
Also worth mentioning, if you get your IP. You could do a "whois 111.222.333.444" command lookup.

That result will show the IP CIDR (Classless Inter-Domain Routing) ranges, that are available from the mobile provider.



Used a random IP found online as an example:
Code:
$ whois 107.77.196.34

...
NetRange:       107.64.0.0 - 107.127.255.255
CIDR:           107.64.0.0/10
...

With that 107.64.0.0/10 cidr notation, it shows that specific network has 4,194,304 available ipv4 addresses.

Now that part I don't think happens or am not sure of, is they wouldn't all be available. Where there's probably some ranges within that range that are being reserved, or in-use by other people.
 
@Neptun2020 hope you don't mind me hijacking this thread, but I took your app.js and built a very basic IP tracking in there to help @C63 with this

I have a collect a list last year using connect and disconnect method. I got more than 200 IP's from one sim card/ one mobile network in my country. and there other GSM network (5 companies) available in my country.

So that part I did manually. I want to learn how to do that automatically for each request and rotating. I just need that mechanism dear. That's the hard part, and the thread owner doing that nicely with using dongle farm.

So here's what you want to do (hope I get the formatting right on the first try).

1. Change into the proxy-monitor folder
Code:
cd proxy-monitor

2. Create the file loggedIps.csv, this will log the IPs in a very simple format of
IP1;How often has this IP been seen
IP2;How often has this IP been seen
...
Code:
sudo nano loggedIps.csv
Save the empty file with Ctrl + O

3. Give your user full read/write access to the loggedIps.csv
Code:
sudo chown -R USERNAME:USERNAME loggedIps.csv

4. Install some node packages
Code:
npm install proper-lockfile
npm install csv-parse

5. Now we will make some changes in the app.js that @Neptun2020 gave us on page 1 of this thread. I'll explain all the changes here, but if you just want to copy paste I will add the full app.js with all changes at the end
In the top part you want to add imports for the 2 packages we installed in the previous step, so after
JavaScript:
const app = express();
which you'll find in line 13, add
JavaScript:
const lockfile = require('proper-lockfile');
const { parse } = require('csv-parse');

6. Add a function to react to a changing IP and write it into the loggedIps.csv. This function is called logDeviceIp and I added it between the changeIp function and the continousCheck function. So after this block that is already in the app.js
JavaScript:
const changeIp = async (device) => {
    console.log(`Changing IP: ${device.ip}`);
    try {
        updateConnectedDevice(device, 'changingIp', 1);
        await changeIpDevice(device);
        updateConnectedDevice(device, 'changingIp', 0);
        updateConnectedDevice(device, 'publicIp', '');
        await logDeviceIp(device, 0);
    } catch (error) {
        console.error(`Error occurred while changing IP for device: ${error.message}`);
    }
};
Add the following
JavaScript:
const logDeviceIp = async (device, attempts) => {
    let ip = await getPublicIp(device);
    if (ip) {
        ip = ip.replace(/(\r\n|\n|\r)/gm, '');
        lockfile.lock('loggedIps.csv', {
            retries: { retries: 100, minTimeout: 10, maxTimeout: 100 }
        })
            .then((release) => {
                let ipFound = 1;
                let rows = [];
                fs.createReadStream('loggedIps.csv')
                    .pipe(parse({delimiter: ';', from_line: 1}))
                    .on('data', function(row) {
                        if(row[0] === ip) {
                            row[1] = parseInt(row[1]) + 1;
                            ipFound = row[1];
                        }
                        rows.push(row);
                    })
                    .on('end', () => {
                        let writeStream = fs.createWriteStream('./loggedIps.csv');
                        if (ipFound <= 1) {
                            let newRow = [ip, 1];
                            rows.push(newRow);
                        }
                        rows.forEach((row) => {
                            writeStream.write(row.join(';') + '\n', () => {
                            });
                        });
                        writeStream.end();
                        console.log('Logged public IP ' + ip + ' for the ' + ipFound + '. time');
                    })
                return release();
            })
            .catch((e) => {
                console.error(e);
            })
    }
    else if (attempts < 10) {
        setTimeout(async () => {
            await logDeviceIp(device, attempts + 1);
        }, 2);
    }
};

7. Now all that's left to do is call this function in the 2 appropriate places. First on initially connecting a device in the function continousCheck. So find the following block
JavaScript:
const continuousCheck = () =>
    setInterval(async () => {
        try {
            if (isChecking) {
                connectedDevices.forEach(async device => {
                    const response = await ping.promise.probe(device.ip, { timeout: config.pingTimeout });
                    if (response.alive) {
                        if ((device.active === 0) && (device.changingIp === 0)) {
                            console.log(`Device ${device.ip} is active`);
                            updateConnectedDevice(device, 'active', 1);
                            const publicIp = await getPublicIp(device);
                            updateConnectedDevice(device, 'publicIp', publicIp);
And after that add this line
JavaScript:
await logDeviceIp(device, 0);

8. Now also add the function call to where a new IP/reconnect is triggered. So find the following block
JavaScript:
const changeIp = async (device) => {
    console.log(`Changing IP: ${device.ip}`);
    try {
        updateConnectedDevice(device, 'changingIp', 1);
        await changeIpDevice(device);
        updateConnectedDevice(device, 'changingIp', 0);
        updateConnectedDevice(device, 'publicIp', '');
And after it add
JavaScript:
await logDeviceIp(device, 0);

9. You're done and every IP that your devices get should be logged in the loggedIps.csv. Either open it via
Code:
nano loggedIps.csv
Or open it with another programm (eg. import it into an appliction for tables like Excel)
I didn't test this too much so hopefully you shouldn't run into any problems. If you want to just get it done quickly, here is the whole new app.js that you can use to replace the other one
 
  • Like
Reactions: C63
Guess the post go too long with the full app.js, so here we go
JavaScript:
const http = require('http');
const request = require('request');
const xml2js = require('xml2js');
const ping = require('ping');
const express = require('express');
const fetch = require('node-fetch');
const fs = require('fs');
const path = require('path');
const readline = require('readline');
const { execSync } = require('child_process');
const process = require('process');
const config = require('./config.js');
const app = express();
const lockfile = require('proper-lockfile');
const { parse } = require('csv-parse');

let connectedDevices = [];
let isChecking = true;
let mode = 3;
let reset = false;

const parseProxyConfig = async () => {
    var proxyConfig = {}
    const fileStream = fs.createReadStream(config.proxyServerDirectory + '3proxy.cfg');
    const rl = readline.createInterface({
        input: fileStream,
        crlfDelay: Infinity,
    });
    for await (const line of rl) {
        if (line.includes('proxy ')) {
            const segments = line.split('-');
            let port, ip;
            for (let segment of segments) {
                if (segment.startsWith('p')) {
                    port = segment.slice(1);
                } else if (segment.startsWith('e')) {
                    ip = segment.slice(1);
                }
            }
            if (ip && port) {
                if (!proxyConfig[ip]) {
                    proxyConfig[ip] = {};
                }
                proxyConfig[ip].port = port;
            }
        }
    }
    return proxyConfig;
};

const getData = async (ip, path, method, headers, requestBody = '') => {
    return new Promise((resolve, reject) => {
        const options = { hostname: ip, path, method, headers };
        const req = http.request(options, (res) => {
            let data = '';
            res.setEncoding('utf8');
            res.on('data', (chunk) => {
                data += chunk;
            });
            res.on('end', () => {
                resolve(data);
            });
        });
        req.on('error', (e) => {
            reject(e);
        });
        if (requestBody) {
            req.write(requestBody);
        }
        req.end();
    });
};


const parseXML = async (data) => {
    return new Promise((resolve, reject) => {
        xml2js.parseString(data, (error, result) => {
            if (error) {
                reject(error);
            } else if (result && result.error) {
                reject(result.error);
            } else {
                resolve(result);
            }
        });
    });
};

const getTokens = async (device) => {
    try {
        const data = await getData(device.ip, '/api/webserver/SesTokInfo', 'GET');
        const result = await parseXML(data);
        return { session: result.response.SesInfo[0], postToken: result.response.TokInfo[0] };
    } catch (error) {
        throw error;
    }
};

const updateConnectedDevice = (device, field, newValue) => {
    const index = connectedDevices.findIndex((connectedDevice) => connectedDevice.interface === device.interface);
    if (index > -1) {
        connectedDevices[index][field] = newValue;
    }
};

const connectDevice = async (device, postToken, session) => {
    try {
        const headers = {
            __RequestVerificationToken: postToken,
            Cookie: session,
            'Content-Type': 'text/xml',
        };
        const chunk = await getData(device.ip, '/api/dialup/mobile-dataswitch', 'POST', headers, "<?xml version='1.0' encoding='UTF-8'?><request><dataswitch>1</dataswitch></request>");
    } catch (error) {
        throw error;
    }
};

const changeIpDevice = async (device) => {
    try {
        const result = execSync('python3 ' + config.changeIpScript + ' --gateway ' + device.ip);
        return result.toString();
    } catch (error) {}
};

const isConnected = (ip) => connectedDevices.some(device => device.ip === ip);

const addDevice = (device) => {
    if (!isConnected(device.ip)) {
        device.publicIp = '';
        device.changingIp = 0;
        connectedDevices.push(device);
    } else {
        console.warn(`Device with IP ${device.ip} is already connected`);
    }
};

const getNewIp = async (ipEnding = 9) => {
    ipEnding = connectedDevices.length > 0 ? connectedDevices.length + 9 : ipEnding;
    const ip = `192.168.${ipEnding}.1`;
    return isConnected(ip) ? getNewIp(ipEnding + 1) : ip;
};

const getPublicIp = async (device) => {
    try {
        const ip = execSync('curl -k --silent --interface ' + device.interface + ' https://eth0.me');
        return ip.toString();
    } catch (error) {}
};

const updateIp = async (device, postToken, session, reset = false, includeDevice = true) => {
    try {
        let newIp;
        if (reset) {
            newIp = config.defaultIP;
            updateConnectedDevice(device, 'active', 0);
            updateConnectedDevice(device, 'publicIp', '');
        } else {
            newIp = await getNewIp();
            if (includeDevice) {
                addDevice({ ip: newIp, active: 0, interface: device.interface, inetIp: device.inetIp, port: device.port });
                updateConnectedDevice(device, 'active', 0);
                updateConnectedDevice(device, 'publicIp', '');
            }
        }
        console.log(`Updating IP to: ${newIp}`);
        const headers = {
            __RequestVerificationToken: postToken,
            Cookie: session,
            'Content-Type': 'text/xml',
        };
        let ipAddressParts = newIp.split('.');
        ipAddressParts.pop();
        let newIpShort = ipAddressParts.join('.');
        const chunk = await getData(device.ip, '/api/dhcp/settings', 'POST', headers, `<?xml version=\"1.0\" encoding=\"UTF-8\"?><request><DnsStatus>1</DnsStatus><DhcpStartIPAddress>${newIpShort}.100</DhcpStartIPAddress><DhcpIPAddress>${newIpShort}.1</DhcpIPAddress><accessipaddress></accessipaddress><homeurl>hi.link</homeurl><DhcpStatus>1</DhcpStatus><DhcpLanN>
        console.log(`IP updated: ${newIp}`);
        if (includeDevice) {
            await changeIp({ ip: newIp, active: 0, interface: device.interface, inetIp: device.inetIp, publicIp: '' });
        }
    } catch (error) {
        throw error;
    }
};

const changeIp = async (device) => {
    console.log(`Changing IP: ${device.ip}`);
    try {
        updateConnectedDevice(device, 'changingIp', 1);
        await changeIpDevice(device);
        updateConnectedDevice(device, 'changingIp', 0);
        updateConnectedDevice(device, 'publicIp', '');
        await logDeviceIp(device, 0);
    } catch (error) {
        console.error(`Error occurred while changing IP for device: ${error.message}`);
    }
};

const logDeviceIp = async (device, attempts) => {
    let ip = await getPublicIp(device);
    if (ip) {
        ip = ip.replace(/(\r\n|\n|\r)/gm, '');
        lockfile.lock('loggedIps.csv', {
            retries: { retries: 100, minTimeout: 10, maxTimeout: 100 }
        })
            .then((release) => {
                let ipFound = 1;
                let rows = [];
                fs.createReadStream('loggedIps.csv')
                    .pipe(parse({delimiter: ';', from_line: 1}))
                    .on('data', function(row) {
                        if(row[0] === ip) {
                            row[1] = parseInt(row[1]) + 1;
                            ipFound = row[1];
                        }
                        rows.push(row);
                    })
                    .on('end', () => {
                        let writeStream = fs.createWriteStream('./loggedIps.csv');
                        if (ipFound <= 1) {
                            let newRow = [ip, 1];
                            rows.push(newRow);
                        }
                        rows.forEach((row) => {
                            writeStream.write(row.join(';') + '\n', () => {
                            });
                        });
                        writeStream.end();
                        console.log('Logged public IP ' + ip + ' for the ' + ipFound + '. time');
                    })
                return release();
            })
            .catch((e) => {
                console.error(e);
            })
    }
    else if (attempts < 10) {
        setTimeout(async () => {
            await logDeviceIp(device, attempts + 1);
        }, 2);
    }
};

const continuousCheck = () =>
    setInterval(async () => {
        try {
            if (isChecking) {
                connectedDevices.forEach(async device => {
                    const response = await ping.promise.probe(device.ip, { timeout: config.pingTimeout });
                    if (response.alive) {
                        if ((device.active === 0) && (device.changingIp === 0)) {
                            console.log(`Device ${device.ip} is active`);
                            updateConnectedDevice(device, 'active', 1);
                            const publicIp = await getPublicIp(device);
                            updateConnectedDevice(device, 'publicIp', publicIp);
                            await logDeviceIp(device, 0);
                        } else if ((device.active === 1) && (device.changingIp === 1)) {
                            updateConnectedDevice(device, 'active', 0);
                        } else if ((device.active === 1) && (device.changingIp === 0) && (!device.publicIp)) {
                            const publicIp = await getPublicIp(device);
                            updateConnectedDevice(device, 'publicIp', publicIp);
                        }
                    } else {
                        if ((device.active === 1) || (device.changingIp === 1)) {
                            console.log(`Device ${device.ip} is offline`);
                            updateConnectedDevice(device, 'active', 0);
                            updateConnectedDevice(device, 'changingIp', 0);
                            updateConnectedDevice(device, 'publicIp', '');
                        }
                    }
                });
            }
        } catch (error) {
            console.error('Error occurred while pinging devices:', error.message);
        }
    }, config.checkInterval);

const processIps = async (ips, reset = false) => {
    let proxyConfig = await parseProxyConfig();
    for (const device of ips) {
        try {
            const response = await ping.promise.probe(device.ip, { timeout: config.pingTimeout });
            if (response.alive) {
                console.log(`Found a device with this IP: ${device.ip}`);
                const { session, postToken } = await getTokens(device);
                await connectDevice(device, postToken, session);
                if (reset) {
                    isChecking = false;
                    console.log(`Resetting to default IP: ${config.defaultIP}`);
                    const newTokens = await getTokens(device);
                    await updateIp(device, newTokens.postToken, newTokens.session, reset);
                    await changeIp({ ip: config.defaultIP, active: 1, interface: device.interface, inetIp: '', publicIp: '' });
                } else if (isConnected(device.ip)) {
                    console.log(`IP already being used. Updating IP: ${device.ip}`);
                    const newTokens = await getTokens(device);
                    await updateIp(device, newTokens.postToken, newTokens.session);
                } else {
                    let port = proxyConfig[device.inetIp] ? proxyConfig[device.inetIp].port : '';
                    addDevice({ ip: device.ip, active: 0, interface: device.interface, inetIp: device.inetIp, port: port });
                }
            }
        } catch (error) {
            console.error(`Error occurred while processing IPs: ${error.message}`);
        }
    }
    continuousCheck();
};

const parseIfconfig = async () => {
    try {
        const ifconfigOutput = execSync('ifconfig');
        const lines = ifconfigOutput.toString().split('\n');
        const devices = {};
        let currentDevice;
        for (const line of lines) {
            if (line.includes('inet ')) {
                const inetIp = line.split('inet ')[1].split(' ')[0];
                if (inetIp.startsWith('192.168.') && inetIp.endsWith('.100')) {
                    let ipAddressParts = inetIp.split('.');
                    ipAddressParts.pop();
                    let newIpShort = ipAddressParts.join('.');
                    devices[currentDevice] = { ip: newIpShort + '.1', inetIp: inetIp, interface: currentDevice, publicIp: '' };
                }
            } else if (line.includes(': flags=')) {
                currentDevice = line.split(':')[0];
            }
        }
        return Object.values(devices);
    } catch (error) {
        console.error('Error while parsing ifconfig:', error.message);
    }

};

const getIps = async () => {
    try {
        return await parseIfconfig();
    } catch (error) {
        console.error('Error while parsing ifconfig:', error.message);
    }
};

const generateIps = () => Array.from({ length: config.maxDevices }, (_, i) => `192.168.${i + 9}.1`);

const defaultIpCheck = () => setInterval(() => cycleDefaultIpCheck(), config.checkInterval);

const cycleDefaultIpCheck = async () => {
    try {
        const response = await ping.promise.probe(config.defaultIP, { timeout: config.pingTimeout });
        if (response.alive) {
            console.log(`New device found with this IP: ${config.defaultIP}`);
            const { session, postToken } = await getTokens({ ip: config.defaultIP });
            await connectDevice({ ip: config.defaultIP }, postToken, session);
            const newTokens = await getTokens({ ip: config.defaultIP });
            await updateIp({ ip: config.defaultIP }, newTokens.postToken, newTokens.session, false, false);
        }
    } catch (error) {
        console.error('Error occurred while pinging devices:', error.message);
    }
};

function create3ProxyConfigFile(ips) {
    let proxyConfigContent = `#! /usr/local/bin/3proxy
daemon
nserver 8.8.8.8
nscache 65536
timeouts 1 5 30 60 180 15 60
auth none
allow * 192.168.0.0/24\n`;
    let port = 3200;
    for (let device of ips) {
        proxyConfigContent += `proxy -p${port} -e${device.inetIp}\n`;
        port++;
    }
    proxyConfigContent += "flush\n";
    fs.writeFileSync(path.join(config.proxyServerDirectory, '3proxy.cfg'), proxyConfigContent, 'utf8');
}

function createStartProxySHFile(ips) {
    let instructions = '';
    let proxySHContent = `sudo echo "Let's setup the IP"\n`;
    for (let device of ips) {
        proxySHContent += `sudo ifconfig ${device.interface} ${device.inetIp}\n`;
    }
    proxySHContent += "sleep 2\nsudo echo \"Let's setup the routes for the proxy\"\n";
    let i = 1;
    for (let device of ips) {
        let ipAddressParts = device.ip.split('.');
        ipAddressParts.pop();
        let newIpShort = ipAddressParts.join('.');
        proxySHContent += `sudo ip route replace ${newIpShort}.0/24 dev ${device.interface} src ${device.inetIp} table gateway${i}
sudo ip route replace default via ${device.ip} dev ${device.interface} table gateway${i}
sudo ip rule add from ${device.inetIp}/32 table gateway${i}
sudo ip rule add to ${device.inetIp}/32 table gateway${i}\n`;
        instructions += `${i}   gateway${i}\n`;
        i++;
    }
    console.log(`Run "sudo nano /etc/iproute2/rt_tables" and add this to the end of the document:\n${instructions}`);
    proxySHContent += `sleep 5
sudo echo "Let's start the proxy"
sudo 3proxy ${config.proxyServerDirectory}3proxy.cfg`;
    fs.writeFileSync(path.join(config.proxyServerDirectory, 'startproxy.sh'), proxySHContent, { encoding: 'utf8', mode: 0o777 });
}

if (process.argv[2] == '1') {
    mode = 1;
} else if (process.argv[2] == '2') {
    mode = 2;
} else {
    mode = 3;
}

if (mode == 1) {
    console.log(`Important: Plug one USB modem in at a time.`);
    console.log(`Wait until the IP address of USB modem has been changed before plugging in the next one!`);
    console.log(`After the IP addresses of all devices have been changed run "node app.js 2" to create your 3proxy.cfg and startproxy.sh files.`);
    generateIps().forEach(async (ip) => {
        console.log('Inside')
        console.log(ip)
        const response = await ping.promise.probe(ip, { timeout: config.pingTimeout })
        console.log('Response')
        console.log(response)
        if (response.alive) {
            console.log(`Found a device with this IP: ${ip}`);
            const { session, postToken } = await getTokens({ ip: ip });
            await connectDevice({ ip: ip }, postToken, session);
            addDevice({ ip: ip });
        }
    });
    defaultIpCheck();

} else if (mode == 2) {
    console.log(`Creating 3proxy.cfg and startproxy.sh files.`);
    getIps()
        .then(ips => {
            const threeProxyPath = path.join(config.proxyServerDirectory, '3proxy.cfg');
            if (!fs.existsSync(threeProxyPath)) {
                create3ProxyConfigFile(ips);
            }

            const startProxyPath = path.join(config.proxyServerDirectory, 'startproxy.sh');
            if (!fs.existsSync(startProxyPath)) {
                createStartProxySHFile(ips);
            }
            console.log(`After you added everything to rt_tables:\n1) Run "sudo ${config.proxyServerDirectory}startproxy.sh" to start 3proxy.\n2) Run "node app.js" to start the proxy monitor.\n3) Visit http://localhost:3000 with your browser.`);
        })
        .catch(error => {});

} else {
    const threeProxyPath = path.join(config.proxyServerDirectory, '3proxy.cfg');
    const startProxyPath = path.join(config.proxyServerDirectory, 'startproxy.sh');
    if ((!fs.existsSync(threeProxyPath)) || (!fs.existsSync(startProxyPath))) {
        console.log(`Error: 3proxy.cfg and startproxy.sh files do not exists.`);
        console.log(`Please run "node app.js 1" first to setup your USB modems!`);
    } else {
        app.get('/changeip', async (req, res) => {
            const { ip } = req.query;
            if (ip) {
                const device = connectedDevices.find(device => device.ip === ip);
                if (device) {
                    await changeIp(device);
                    res.send('');
                } else {
                    console.log(`No device found with IP ${ip}`);
                    res.status(404).send('Device not found');
                }
            } else {
                console.log(`IP is required`);
                res.status(400).send('IP is required');
            }
        });
        app.get('/devices', (req, res) => {
            const devicesWithDetails = connectedDevices.map(device => {
                return {
                    ip: device.ip,
                    interface: device.interface ? device.interface : 'Unknown',
                    inetIp: device.inetIp ? device.inetIp : 'Unknown',
                    port: device.port ? device.port : 'Unknown',
                    active: device.active,
                    publicIp: device.publicIp ? device.publicIp : 'Unknown'
                };
            });
            res.send(devicesWithDetails);
        });
        app.get('/', (req, res) => {
            res.send(`
        <!DOCTYPE html>
        <html>
            <head>
                <meta charset="utf-8"/>
                <meta name="viewport" content="width=device-width, initial-scale=1">
                <title>Device Status</title>
                <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" />
                <style>
                    .status-circle {
                        display: inline-block; width:10px; height:10px; border-radius: 50%;
                    }
                    .status-circle.green { background-color:green; }
                    .status-circle.orange { background-color:orange; }
                    .status-circle.red { background-color:red; }
                </style>
            </head>
            <body>
                <div class="container py-4">
                    <div class="table-responsive">
                        <table class="table" id="devicesTable">
                            <thead>
                                <tr>
                                    <th>Interface</th><th>IP</th><th>Proxy Port</th><th>Status</th><th>Public IP</th><th>Action</th>
                                </tr>
                            </thead>
                            <tbody><tr><td colspan="6" class="text-center">Loading...</td></tr></tbody>
                        </table>
                    </div>
                </div>
                <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
                <script>
                    async function refreshTable() {
                        const res = await fetch('/devices');
                        const devices = await res.json();
                        if(devices.length === 0){
                            document.querySelector('#devicesTable tbody').innerHTML = '<tr><td colspan="6" class="text-center">No devices found.</td></tr>';
                        } else {
                            let html = '';
                            for (let device of devices) {
                                const statusCircle = '<span id="status-' + device.interface +'" class="status-circle ' + ((device.publicIp === \'Unknown\') ? "orange" : (device.active ? "green" : "red")) + '"></span>';
                                const changeIpButton = '<button id="changeIpButton-' + device.interface +'" onclick="changeIpOfDevice(\\\'\' + device.ip + \'\\\', \\\'\' + device.interface + \'\\\')" class="btn btn-primary"' + (device.active ? "" : " disabled") + '>New IP</button>';
                                html += '<tr><td>' + [device.interface, device.ip, device.port, statusCircle, device.publicIp,changeIpButton].join('</td><td>') + '</td></tr>';
                            }
                            document.querySelector('#devicesTable tbody').innerHTML = html;
                        }
                    }
                    async function changeIpOfDevice(ip, interface) {
                        const button = document.querySelector('#changeIpButton-' + interface);
                        button.disabled = true;
                        const status = document.querySelector('#status-' + interface);
                        if (status.classList.contains('green')) {
                            status.classList.remove('green');
                            status.classList.add('red');
                        }
                        await fetch('/changeip?ip=' + ip);
                    }
                    refreshTable();
                    setInterval(refreshTable, 3000);
                </script>
            </body>
        </html>
        `);
        });
        app.listen(config.serverPort, () => {
            console.log(`Proxy monitor listening on port ${config.serverPort}`);
            getIps()
                .then(ips => processIps(ips, reset))
                .catch(error => console.error('Error while getting IPs:', error.message));
        });
    }
}
 
There's so much valuable information in here. Thank you very much friend.

You’re most welcome, once you get around to testing it please let me know if it works, as I said with my 1 stick I could do very limited testing
 
Good luck on your journey mate and thank you for valuable information you are giving...
 
Back
Top