My Journey (with guides and code)

Neptun2020

Junior Member
Joined
Oct 25, 2020
Messages
122
Reaction score
130
A few days ago, I came across @lucky.sparks https://www.blackhatworld.com/seo/this-is-my-journey.1493986/ where he stated in his introduction, "There won't be any structure, plans, or bullet points. I don't have any specific goals." This inspired me to post on my own journey here.

While I do have my personal goal(s), there's no concrete structure or major plan - just a general direction. I prefer to take things step by step, as it allows me to focus more on overcoming potential hurdles.

In this journey, I'll share code snippets and ideas that could be useful to anyone reading here. I won't be sharing in detail what I'm working on.

The first thing I need to start my journey is some mobile proxies, so today I'll start by sharing a simple guide and scripts for setting up and managing your own mobile proxies with a quick interface and a very simple API. I've found various guides here on BHW, but they often had errors or were missing information. So here's my attempt to help those who might have encountered issues with those guides. My solution for a mobile proxy is a quick and rough one that I scripted quickly for myself. It's not perfect by any means - it's just a simple solution that works for me. Since I'll be using it on my local network, I won't include authentication.

I am using Huawei E3372 USB sticks and Ubuntu. Although it might work with other similar Huawei sticks, I have not personally tested it.

It elaborates on the concepts and principals found in these two guides: https://www.blackhatworld.com/seo/diy-how-to-create-your-own-4g-proxy.1234185/ and https://scrapingfish.com/blog/byo-mobile-proxy-for-web-scraping

The change-ip.py file below was sourced from https://scrapingfish.com/blog/byo-mobile-proxy-for-web-scraping

Use this guide at your own risk.

1. Open a terminal window in Ubuntu.

2. Enter the following commands:
Code:
sudo apt-get update
sudo apt-get upgrade

3. Open up the sysctl.conf file by typing the command:
Code:
sudo nano /etc/sysctl.conf

4. From here, scroll down and remove the # sign before the line:
Code:
net.ipv4.ip_forward=1

Save the file by pressing Ctrl+O and exit using Ctrl+X

5. Enter the following command:
Code:
sudo apt-get -y install git fail2ban software-properties-common build-essential libevent-dev libssl-dev net-tools curl npm nodejs python3-pip

6. Clone the 3proxy repository using the following commands:
Code:
git clone https://github.com/3proxy/3proxy
cd 3proxy

7. Type in sudo nano src/proxy.h and press enter. This opens a document where you need to scroll until you find this line:
Code:
#define MAXUSERNAME 128

Directly above this line, write the following line:
Code:
#define ANONYMOUS 1

Save this file by pressing Ctrl+O and close with Ctrl+X

8. Type the following commands:
Code:
sudo ln -s Makefile.Linux Makefile
sudo make
sudo make install
sudo systemctl is-enabled 3proxy.service

9. Create a directory named proxy-monitor using the commands:
Code:
cd ..
mkdir proxy-monitor
cd proxy-monitor

10. Create the file config.js by typing in:
Code:
sudo nano config.js

Paste the following in the file:
JavaScript:
module.exports = {
    /* Location of the change-ip.py python script */
    changeIpScript: '/home/YOUR_USERNAME/proxy-monitor/change-ip.py',

    /* Location of your 3proxy installation */
    proxyServerDirectory: '/home/YOUR_USERNAME/3proxy/',

    /* The default IP address for the Huawei usb sticks */
    defaultIP: '192.168.8.1',

    /* The maximum number of Huawei usb sticks connected */
    maxDevices: 20,

    /* The port in which the node.js express server runs */
    serverPort: 3000,

    /* The time limit for sending ping commands */
    pingTimeout: 5,

    /* The time interval for continuous check in milliseconds */
    checkInterval: 3000,
};

Replace YOUR_USERNAME with your preferred username.
You can define the maximum Huawei E3372 USB sticks to be used here, currently set at 20:
Code:
maxDevices: 20

Save and close the file using Ctrl+O and Ctrl+X respectively.

11. Create the file app.js by typing in:
Code:
sudo nano app.js

Paste the following in the file:

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();

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><DhcpLanNetmask>255.255.255.0</DhcpLanNetmask><SecondaryDns>${newIpShort}.1</SecondaryDns><PrimaryDns>${newIpShort}.1</PrimaryDns><DhcpEndIPAddress>${newIpShort}.100</DhcpEndIPAddress><DhcpLeaseTime>86400</DhcpLeaseTime></request>`);
        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', '');
    } catch (error) {
        console.error(`Error occurred while changing IP for device: ${error.message}`);
    }
};

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);
                        } 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) => {
        const response = await ping.promise.probe(ip, { timeout: config.pingTimeout })
        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));
        });
    }
}

Save and exit using Ctrl+O and Ctrl+X.

12. Create the file change-ip.py by typing in:
sudo nano change-ip.py

Paste the following in the file:

Python:
import time

from huawei_lte_api.Client import Client
from huawei_lte_api.Connection import Connection
from huawei_lte_api.enums.net import LTEBandEnum, NetworkBandEnum, NetworkModeEnum


def main(gateway: str, timeout: float = 5.0):
    with Connection(url=f"http://{gateway}/", timeout=timeout) as connection:
        lte_client = Client(connection)
        net_mode_response = lte_client.net.net_mode()
        net_mode = net_mode_response.get(
            "NetworkMode", NetworkModeEnum.MODE_4G_3G_AUTO.value
        )
        new_net_mode = (
            NetworkModeEnum.MODE_4G_ONLY
            if not net_mode == NetworkModeEnum.MODE_4G_ONLY.value
            else NetworkModeEnum.MODE_4G_3G_AUTO
        )
        time.sleep(0.1)
        lte_client.net.set_net_mode(
            lteband=LTEBandEnum.ALL,
            networkband=NetworkBandEnum.ALL,
            networkmode=new_net_mode,
        )
        time.sleep(3.0)
        print("Done")


if __name__ == "__main__":
    import argparse

    parser = argparse.ArgumentParser(
        description="Reset IP address of a 4G modem with HiLink interface"
    )
    parser.add_argument(
        "--gateway", type=str, required=True, help="modem gateway address"
    )
    parser.add_argument(
        "--timeout",
        type=float,
        required=False,
        default=5.0,
        help="modem connection timeout in seconds (default=5.0)",
    )
    args = parser.parse_args()
    main(gateway=args.gateway, timeout=args.timeout)

Again, save and close the file using Ctrl+O and Ctrl+X.

13. We need to install some required modules before proceeding. Run the following command:
Code:
python3 -m pip install huawei-lte-api
npm install xml2js ping express request readline fs node-fetch@2

14. Next step is to change the default IP addresses (192.168.8.1) of the Huawei E3372 USB sticks.
Run the command below and sequentially add one USB stick after another once the IP has been changed.
The IPs of the sticks will start from 192.168.9.1 to 192.168.10.1 and so on.

The command to run is:
Code:
node app.js 1

After reassigning IP addresses to all Huawei E3372 USB sticks, press Ctrl+C to terminate the app.

15. Let the app create the 3proxy.cfg and startproxy.sh files by running the following command:
Code:
node app.js 2

16. Add the output from step 15 to rt_tables using the following command:
Code:
sudo nano /etc/iproute2/rt_tables

Add the information to the end of the document.

Save and close the file using Ctrl+O and Ctrl+X.

17. Finally, launch the 3proxy server by running this command (replace YOUR_USERNAME with your username):
Code:
sudo /home/YOUR_USERNAME/3proxy/startproxy.sh

18. While you are still in the proxy-monitor directory, start the proxy monitor using the command:
Code:
node app.js

19. Navigate to http://localhost:3000 to manage your proxies.

It also provides a simple API.

To list all devices in JSON format, visit:
http://localhost:3000/devices
To dynamically change/rotate the public IP address of a specific device, visit:
http://localhost:3000/changeip?ip=192.168.9.1
Now, you can use the proxies in the following way:
localhost:3200 corresponds to the first Huawei E3372 USB stick
localhost:3201 corresponds to the second Huawei E3372 USB stick

You can test your proxies like this:
Code:
curl --proxy localhost:3200 eth0.me
curl --proxy localhost:3201 eth0.me
curl --proxy localhost:3202 eth0.me
 
Last edited:
Good luck! Are you going to start a proxy business?
Thank you!
No, I am not starting a proxy business. I just need a lot of mobile proxies for my journey and it is cheaper to create and run them myself.
 
Last edited:
Good luck
following your journey :)
 
Where do you learn how to code and what do you think are the best languages?

Im currently doing a python mega course that I got off of BHW but im looking for java, nodeJS and other good languages
 
Where do you learn how to code and what do you think are the best languages?
Start with a very small project and expand your knowledge by working on it. As the saying goes: "Read. Read code. Code."
The "best language" is the one that suits the tasks you are looking to accomplish. Languages are tools - pick the one(s) you feel most comfortable with.
 
So whats your plan? I guess some kind of social media boting? Because you mentioned Lucky and his journey.
 
Where do you learn how to code and what do you think are the best languages?

Im currently doing a python mega course that I got off of BHW but im looking for java, nodeJS and other good languages
Years ago when i discovered Python, I thought: what a boring useless coding languange.
That time I used Delphi/Pascal and C/C++ mostly.

But later I understood how powerful Python is actually. It can do literally everything.
Now I got tons of Python books and using it alot.

Of course same with NodeJS and other new technologies. All they are very good and lots of good tutorials on YT.
You can do lots of stuff with each of them.
Just find time to learn this all and try some test projects.


@Neptun2020
any ideas where to get the Huawei E3372 USB sticks for very cheap?
Directly from China?
In EU they are pretty expensive. 30-40€ a piece.
Bying 20 or 30 gets costly, specially when you dont know if any automation with them brings any profit at all.
 
Last edited:
So whats your plan? I guess some kind of social media boting? Because you mentioned Lucky and his journey.
I specifically mentioned @lucky.sparks journey because it was the reason for me to publicly start mine and share interesting things along the way. In every journey, you can find something useful for your own - for example, lucky.sparks mentioned why he is using Apple's M1s - a tip that I gladly incorporated in my own setup. Maybe I mention something here that helps other people on this forum. And no, what I am doing is something completely different from what lucky.sparks is doing.
 
I specifically mentioned @lucky.sparks journey because it was the reason for me to publicly start mine and share interesting things along the way. In every journey, you can find something useful for your own - for example, lucky.sparks mentioned why he is using Apple's M1s - a tip that I gladly incorporated in my own setup. Maybe I mention something here that helps other people on this forum. And no, what I am doing is something completely different from what lucky.sparks is doing.
OK. But we all know what Lucky is doing from all his previous journeys. And what exactly you are gonna do? Something similar as Lucky? Or Some kind of acc creation and selling farm?
 
any ideas where to get the Huawei E3372 USB sticks for very cheap?
Directly from China?
In EU they are pretty expensive. 30-40€ a piece.
Bying 20 or 30 gets costly, specially when you dont know if any automation with them brings any profit at all.
A couple of years ago, I bought Huawei E3372 in bulk from a company that no longer needed them, so I got them at a very good price. Obviously, if you personally can't profit from them, then I wouldn't recommend buying them.
 
Last edited:
OK. But we all know what Lucky is doing from all his previous journeys. And what exactly you are gonna do? Something similar as Lucky? Or Some kind of acc creation and selling farm?
My plan for this journey is to share my solutions to the "problems" I encounter along the way. However, I don't intend to go into detail about what I am working on, as I believe that it won't be beneficial to anyone reading.
 
Good luck with whatever your working on. Will you be doing automation of some kind? Currently setting up my own 4g proxy so will bookmark your post :)

Btw, What hardware did you use with the dongles? (As in pi, odroid, pc etc)
Using a pi myself but its extremely painful to get it to detect the dongle as network instead of mass storage device
 
I purchased a lot of cheap and old Sony phones from 2015/2016 (with Android 7/8), and for my project, I needed to upgrade them to at least Android 11. The only problem is Sony does not officially support this, so I had to find a different approach.

Let's first get everything we need to get started.
Disclaimer: I am using a non-English version of Windows 11, so some of the translations I provided below (regarding buttons, etc.) may be slightly different in the English version.

As always, use this guide at your own risk. You could potentially make your phone unusable.

1. Create directories where all the necessary files will be stored.
Here is an example of how I prefer to categorize mine:
Code:
c:\phones
c:\phones\platform-tools
c:\phones\usb-driver
c:\phones\NAME_OF_PHONE_MODEL

2. Download ADB from here: https://developer.android.com/studio/releases/platform-tools.
Click on "Download SDK Platform-Tools for Windows" to begin the download.
Unzip the downloaded file into your "c:\phones\platform-tools" directory.

3. Next, download the Google USB Driver from this link: https://developer.android.com/studio/run/win-usb.
Click on "Download the Google USB Driver ZIP file (ZIP)" to start the download.
Unzip the downloaded file into your "c:\phones\usb-driver" directory.

4. Add the "c:\phones\platform-tools" directory to the PATH system variable by clicking on the Windows "Start" symbol and typing "path". Click on the "Edit System Environment Variables," then "Environment Variables".
In System Variables, find the PATH environment variable and select it to edit.
If there's no PATH environment variable, click "New".
In the Edit System Variable (or New System Variable) window, modify the PATH environment variable to include your "c:\phones\usb-driver" directory.
Click OK and close remaining windows.

5. Depending on your phone model, you need to download various files to be stored in the "c:\phones\NAME_OF_PHONE_MODEL" directory.
Let's assume that the phone in question is the "Sony Xperia Z1 compact".
Search for site:forum.xda-developers.com "Sony Xperia Z1 compact" "Android 11" on google.
The first result should be this link: https://forum.xda-developers.com/t/rom-unofficial-11-0-signed-ota-lineage-os-18-1-for-xperia-z1-compact.4199113/.
Visit this site and scroll down where it says "Download".
Click on the "SourceForge" link.
You can choose between a version of LineageOS 18.1 with pre-installed microG or not. If you prefer to use OpenGapps instead, download the version without microG and also this file: https://opengapps.org/?api=11.0&variant=pico&arm.
(If you're wondering where I got this information from, it can be found directly on the page above ;))
Save these files in your "c:\phones\SonyXperiaZ1compact" directory (the "c:\phones\NAME_OF_PHONE_MODEL" directory from above) .

We also need to download the Team Win Recovery Project (TWRP) as recommended on the same page.
Click on the provided link, which takes you to https://forum.xda-developers.com/t/recovery-unofficial-amami-twrp-3-4-0.3960699/.
Scroll down to download and click on the "SourceForge" link.
Download the .img file, rename it to "recovery.img," and save it in your "c:\phones\SonyXperiaZ1compact\" directory.

6. While your phone is disconnected from the computer, turn it on and wait for it to boot.
Go to Settings -> System -> About phone and tap on the Build Number multiple times until is says that you are now a developer.
Go back and enter the developer options.
Make sure the bootloader (or OEM) option is active. If it's greyed out, factory reset your device and (IMPORTANT!) connect it to your Wi-Fi during the setup process. You will then be able to activate the option.
Scroll down and also activate "USB debugging" before closing all settings and returning to the home screen.

7. Dial *#06# on your phone and write down the IMEI code (a dual sim phone will display two IMEI codes, but only write down the first one).

8. Visit https://developer.sony.com/open-source/aosp-on-xperia-open-devices/get-started/unlock-bootloader.
Select your device ("Sony Xperia Z1 compact" in our case) at the bottom, type in your IMEI code from step 7, check all boxes, and hit "Submit."
Write down your unlock code!

9. Connect your phone to your computer, ensuring to accept (and checking) all prompts that appear on the phone screen.

10. In the Windows Explorer, open your "c:\phones\SonyXperiaZ1compact\" directory, right-click, and choose "Open in Terminal".
(or just go to the directory "c:\phones\SonyXperiaZ1compact\" using the terminal).

11. Type
Code:
adb reboot bootloader
and wait for your phone screen to go black.
If you encounter an error saying "error: more than one device/emulator," kill the adb server with the command
Code:
adb kill-server
and rerun
Code:
adb reboot bootloader

12. Open Windows' "Device Manager." You'll see your USB device pop up as "S1Boot Fastboot". Double click it and click "Update drivers." Choose "Search my computer...", "Pick from a list..." and select the first option before proceeding.
Click "Disk" and navigate to the "c:\phones\usb-driver" directory and confirm. Select "Android ADB Interface" and continue.

13. Run
Code:
fastboot devices
to see your device.
Next, type
Code:
fastboot oem unlock 0x<your_unlock_code>
replacing <your_unlock_code> with the unlock code from step 8.

14. Run
Code:
fastboot flash recovery recovery.img
followed by
Code:
fastboot reboot

15. Disconnect your phone from your computer and hold the VOLUME UP and POWER BUTTON until your phone vibrates three times. Wait a few seconds before continuing with the next step.

16. Press the POWER BUTTON and VOLUME DOWN. Release the POWER BUTTON as the device starts but maintain pressing the VOLUME DOWN button for several more seconds.
TWRP (Team Win Recovery Project) should launch.
You can create a backup if you want before we continue.
Choose "Wipe," then "Swipe to Factory Reset." Confirm by typing "yes".

Connect your phone to your computer, and now you should be able to transfer files from your computer to your phone.
Copy the files from "c:\phones\SonyXperiaZ1compact\" to your phone (excluding recovery.img).
Return to the TWRP start screen on your phone.

17. Choose "Install" on your phone. Browse and select the uploaded file(s).
If you have two ore more files, select the one beginning with "lineage-" first and confirm.
The click on "Add more Zips" and select the remaining files.
"Swipe to confirm Flash."

Congratulations! You should now have Android 11 on your Sony Xperia Z1 compact.
 
Last edited:
Good luck with whatever your working on. Will you be doing automation of some kind? Currently setting up my own 4g proxy so will bookmark your post :)

Btw, What hardware did you use with the dongles? (As in pi, odroid, pc etc)
Using a pi myself but its extremely painful to get it to detect the dongle as network instead of mass storage device
Thank you. Yes, automation is involved. I always want my projects to be mostly autonomous once they are up and running.
I am using an old, refurbished Fujitsu Esprimo Q920 (with 16 GB RAM) with the current version of Ubuntu.
The dongles are connected to the computer with a powered USB hub.
 
Back
Top