Neptun2020
Junior Member
- Oct 25, 2020
- 122
- 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:
3. Open up the sysctl.conf file by typing the command:
4. From here, scroll down and remove the # sign before the line:
Save the file by pressing Ctrl+O and exit using Ctrl+X
5. Enter the following command:
6. Clone the 3proxy repository using the following commands:
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:
Directly above this line, write the following line:
Save this file by pressing Ctrl+O and close with Ctrl+X
8. Type the following commands:
9. Create a directory named proxy-monitor using the commands:
10. Create the file config.js by typing in:
Paste the following in the file:
Replace YOUR_USERNAME with your preferred username.
You can define the maximum Huawei E3372 USB sticks to be used here, currently set at 20:
Save and close the file using Ctrl+O and Ctrl+X respectively.
11. Create the file app.js by typing in:
Paste the following in the file:
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:
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:
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:
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:
16. Add the output from step 15 to rt_tables using the following command:
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):
18. While you are still in the proxy-monitor directory, start the proxy monitor using the command:
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:
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: