Skip to content

Instantly share code, notes, and snippets.

@ammarfaizi2
Last active October 5, 2023 15:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ammarfaizi2/6217dcac82e0c3e177b5f60c0e8a109e to your computer and use it in GitHub Desktop.
Save ammarfaizi2/6217dcac82e0c3e177b5f60c0e8a109e to your computer and use it in GitHub Desktop.
<?php
// SPDX-License-Identifier: GPL-2.0-only
const OWRT_HOST = "192.168.33.1";
const OWRT_USER = "root";
const OWRT_PASS = "root password here";
class OWRTJsonRPC
{
/**
* @var string
*/
private string $host;
/**
* @var int
*/
private int $port;
/**
* Either HTTP or HTTPS.
*
* @var string
*/
private string $pre;
/**
* @var string
*/
private string $baseurl;
/**
* @var ?string
*/
private ?string $token = NULL;
/**
* Curl resource.
*
* @var resource
*/
private $ch;
/**
* @param string $host
* @param int $port
* @param bool $https
* @throws \Exception
*
* Constructor.
*/
public function __construct(string $host, ?int $port = NULL, bool $https = false)
{
$this->host = $host;
$this->pre = $https ? "https" : "http";
if ($port === NULL)
$this->port = $https ? 443 : 80;
else
$this->port = $port;
$this->baseurl = "{$this->pre}://{$this->host}:{$this->port}";
$this->ch = curl_init();
if (!$this->ch)
throw new \Exception("curl_init() failed");
}
/**
* Destructor.
*/
public function __destruct()
{
if ($this->token)
$this->logout();
curl_close($this->ch);
}
/**
* Throws an exception if the token is not set.
*
* @throws \Exception
* @return void
*/
private function mustHaveToken(): void
{
if (!$this->token)
throw new \Exception("Unauthorized");
}
/**
* @param string $endpoint
* @param mixed $data
* @param array $options
* @return string
* @throws \Exception
*/
private function icurl(string $endpoint, $data = NULL, array $options = []): string
{
$opt = [
CURLOPT_URL => $endpoint,
CURLOPT_HEADER => false,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_RETURNTRANSFER => true,
];
if ($data !== NULL) {
$opt[CURLOPT_POST] = true;
$opt[CURLOPT_POSTFIELDS] = $data;
}
foreach ($options as $k => $v)
$opt[$k] = $v;
curl_setopt_array($this->ch, $opt);
$out = curl_exec($this->ch);
if ($out === false) {
$err = curl_error($this->ch);
$ern = curl_errno($this->ch);
throw new \Exception("curl_exec() failed: $err ($ern)");
}
return $out;
}
/**
* @param string $user
* @param string $pass
* @return bool
*/
public function login(string $user, string $pass): bool
{
$url = "{$this->baseurl}/cgi-bin/luci/";
$data = http_build_query([
"luci_username" => $user,
"luci_password" => $pass
]);
$out = $this->icurl($url, $data, [
CURLOPT_HEADER => true,
CURLOPT_HTTPHEADER => [
"Content-Type: application/x-www-form-urlencoded",
"Content-Length: " . strlen($data)
]
]);
/*
* Parse `sysauth_http=token` cookie from the response header.
*/
preg_match("/sysauth_https?=([a-z0-9]+)/", $out, $matches);
if (count($matches) < 2)
return false;
$this->token = $matches[1];
return true;
}
/**
* @return void
*/
public function logout(): void
{
if (!$this->token)
return;
$url = "{$this->baseurl}/cgi-bin/luci/admin/logout";
$this->icurl($url, NULL, [
CURLOPT_HTTPHEADER => [
"Cookie: sysauth_http={$this->token}"
]
]);
$this->token = NULL;
}
/**
* @return array
*/
private function execJrpc($json): ?array
{
$url = sprintf("%s/ubus/?%d", $this->baseurl, time());
$out = $this->icurl($url, $json, [
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"Content-Length: " . strlen($json),
"Cookie: sysauth_http={$this->token}"
]
]);
$out = json_decode($out, true);
if (!$out[0]["result"])
return NULL;
return $out[0]["result"];
}
/**
* @param string $method
* @param array $params
* @return string
*/
private function jrpc($method, array $params): string
{
$fixed_params = array_merge([$this->token], $params);
return json_encode([
[
"jsonrpc" => "2.0",
"method" => $method,
"params" => $fixed_params,
"id" => 1
]
]);
}
/**
* @return ?array
*/
public function getNetworkDevices(): ?array
{
$this->mustHaveToken();
$json = $this->jrpc("call", ["network.interface","dump", (object)[]]);
return $this->execJrpc($json);
}
}
function find_biznet_ipv6_pd(OWRTJsonRPC $owrt): ?string
{
$ifaces = NULL;
$res = $owrt->getNetworkDevices();
foreach ($res as $v) {
if (!isset($v["interface"]))
continue;
if (!is_array($v["interface"]))
continue;
$ifaces = $v["interface"];
break;
}
if (!$ifaces)
return NULL;
foreach ($ifaces as $iface) {
if ($iface["interface"] !== "WBIZNET0_6")
continue;
$ret = &$iface["ipv6-prefix"][0]["address"];
if (!isset($ret))
return NULL;
return $ret;
}
return NULL;
}
function reset_tor(string $cur_ip6pd)
{
$tpath = "/home/ammarfaizi2/app/tor_home";
echo shell_exec("pkill -e tor\$");
for ($i = 1; $i <= 4; $i++) {
$torrc = file_get_contents("{$tpath}/cgk00{$i}");
$torrc = preg_replace("/Address \[.+\]/", "Address [{$cur_ip6pd}700{$i}]", $torrc);
file_put_contents("{$tpath}/cgk00{$i}", $torrc);
}
echo "Waiting for 5 seconds...\n";
sleep(5);
for ($i = 1; $i <= 4; $i++)
echo shell_exec("su ammarfaizi2 -c \"taskset -c 0,4,1,5 ionice -c 3 nice -n 40 chrt --idle 0 /usr/local/bin/tor -f /home/ammarfaizi2/app/tor_home/cgk00{$i} 2>&1\"");
echo shell_exec("su ammarfaizi2 -c \"taskset -c 0,4,1,5 ionice -c 3 nice -n 40 chrt --idle 0 /usr/local/bin/tor -f /home/ammarfaizi2/app/tor_home/aa_no_relay 2>&1\"");
}
function try_apply_ipv6_pd(OWRTJsonRPC $owrt): int
{
$old_ip6pd = @file_get_contents("/home/ammarfaizi2/.ip6pd");
$cur_ip6pd = find_biznet_ipv6_pd($owrt);
if (!$cur_ip6pd) {
printf("No IPv6 PD found\n");
return 1;
}
printf("Cur IPv6 PD: %s\n", $cur_ip6pd);
printf("Old IPv6 PD: %s\n", $old_ip6pd);
if ($cur_ip6pd === $old_ip6pd) {
printf("IPv6 PD is not changed\n");
return 0;
}
printf("IPv6 PD is changed\n");
file_put_contents("/home/ammarfaizi2/.ip6pd", $cur_ip6pd);
echo shell_exec("sudo bash /home/ammarfaizi2/init_net.sh 2>&1");
reset_tor($cur_ip6pd);
return 0;
}
function main(): int
{
$owrt = new OWRTJsonRPC(OWRT_HOST);
printf("Logging in...\n");
if (!$owrt->login(OWRT_USER, OWRT_PASS)) {
printf("Login failed\n");
return 1;
}
$ret = try_apply_ipv6_pd($owrt);
printf("Logging out...\n");
$owrt->logout();
return $ret;
}
exit(main());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment