Fix awg0 key fetch, fix data counter, update timeouts, update gitignore

This commit is contained in:
esefxdz committed 2026-05-29 18:39:51 +03:00
1 parent 688c5c7107
commit bec138fbad
3 files changed
+68 -30

No files matched your search

+1
View File
@@ -66,3 +66,4 @@ local_packages/*/.dart_tool/
android/key.properties android/key.properties
lib/logic/backup/ lib/logic/backup/
00-FULL-REPORT.md 00-FULL-REPORT.md
server full picture.txt
+2 -2
View File
@@ -25,14 +25,14 @@ class HivemindService {
}); });
final fakeAdmobPingUrl = Uri.parse( final fakeAdmobPingUrl = Uri.parse(
'${AppConfig.hivemindApiBase}/admob/callback?signature=test&key_id=test&custom_data=${Uri.encodeComponent(customData)}'); '${AppConfig.hivemindApiBase}/admob/callback?signature=test&key_id=test&custom_data=${Uri.encodeComponent(customData)}');
await http.get(fakeAdmobPingUrl).timeout(const Duration(seconds: 2)); await http.get(fakeAdmobPingUrl).timeout(const Duration(seconds: 8));
} catch (_) {} } catch (_) {}
// ────────────────────────────────────────── // ──────────────────────────────────────────
int attempts = 0; int attempts = 0;
while (attempts < 15) { while (attempts < 15) {
try { try {
final response = await http.get(url).timeout(const Duration(seconds: 3)); final response = await http.get(url).timeout(const Duration(seconds: 10));
if (response.statusCode == 200) { if (response.statusCode == 200) {
final data = jsonDecode(response.body); final data = jsonDecode(response.body);
+65 -28
View File
@@ -106,12 +106,14 @@ def init_wireguard():
print(f"[NAT] Applying masquerade for /16 subnet...") print(f"[NAT] Applying masquerade for /16 subnet...")
run_cmd(f"iptables -t nat -A POSTROUTING -s 10.8.0.0/16 -j MASQUERADE", ignore_errors=True) run_cmd(f"iptables -t nat -A POSTROUTING -s 10.8.0.0/16 -j MASQUERADE", ignore_errors=True)
pubkey = run_cmd(f"wg show {WG_INTERFACE} public-key") # Key MUST be read from host awg0 directly (not from Docker's wg0).
# The phone connects to awg0 on port 4433 — Docker's wg0 has a different key.
pubkey = run_cmd("awg show awg0 public-key")
if pubkey: if pubkey:
SERVER_PUBKEY = pubkey SERVER_PUBKEY = pubkey
print(f"[WG] Server Public Key cached: {SERVER_PUBKEY}") print(f"[WG] Server Public Key cached from awg0: {SERVER_PUBKEY}")
else: else:
print("[WG] WARNING: Could not fetch Server Public Key!") print("[WG] WARNING: Could not fetch awg0 public key! Check that awg is installed on host.")
def _class_id(ip): def _class_id(ip):
@@ -135,23 +137,36 @@ def remove_throttle(ip):
def get_wireguard_stats(): def get_wireguard_stats():
"""Returns { "10.8.0.2": {"pubkey": "...", "total_bytes": 1234}, ... }""" """Returns { "10.8.X.Y": {"pubkey": "...", "total_bytes": 1234}, ... }
output = run_cmd(f"wg show {WG_INTERFACE} dump") Reads directly from the host's awg0 interface (not Docker's wg0).
if not output: Uses two separate commands to avoid AmneziaWG dump column-layout differences.
"""
# Step 1: pubkey -> (rx_bytes, tx_bytes)
transfer_out = run_cmd("awg show awg0 transfer")
# Step 2: pubkey -> ip/32
allowed_out = run_cmd("awg show awg0 allowed-ips")
if not transfer_out or not allowed_out:
return {} return {}
stats = {} # Build pubkey -> IP map from allowed-ips
lines = output.splitlines()[1:] pubkey_to_ip = {}
for line in lines: for line in allowed_out.splitlines():
parts = line.split('\t') parts = line.split('\t')
if len(parts) >= 8: if len(parts) >= 2:
pubkey_to_ip[parts[0]] = parts[1].split('/')[0]
# Build IP -> stats from transfer bytes
stats = {}
for line in transfer_out.splitlines():
parts = line.split('\t')
if len(parts) >= 3:
pubkey = parts[0] pubkey = parts[0]
allowed_ips = parts[3].split('/')[0] ip = pubkey_to_ip.get(pubkey)
rx = int(parts[5]) if ip:
tx = int(parts[6]) stats[ip] = {
stats[allowed_ips] = {
"pubkey": pubkey, "pubkey": pubkey,
"total_bytes": rx + tx "total_bytes": int(parts[1]) + int(parts[2])
} }
return stats return stats
@@ -394,23 +409,35 @@ def admob_callback():
{ "device_id": "...", "public_key": "...", "ad_type": "main_ad"|"bonus_ad" } { "device_id": "...", "public_key": "...", "ad_type": "main_ad"|"bonus_ad" }
""" """
try: try:
signature = request.args.get('signature') # ======================================================================
key_id = request.args.get('key_id') # ⚠️ ADMOB BYPASS (TEMPORARY FOR APP REVIEW)
# DELETE THIS ENTIRE BLOCK WHEN YOU WANT TO ENABLE REAL ADS
# ======================================================================
custom_data_str = request.args.get('custom_data') custom_data_str = request.args.get('custom_data')
# Google sends a verification ping with signature+key_id but no custom_data
if not custom_data_str: if not custom_data_str:
return "OK", 200 # Verification ping from Google dashboard return "OK", 200
# ======================================================================
if not all([signature, key_id]): # ======================================================================
return "Missing parameters", 400 # ✅ REAL ADMOB CODE
# UNCOMMENT THIS ENTIRE BLOCK WHEN YOU WANT TO ENABLE REAL ADS
# ⚠️ TEMP: Signature verification disabled for Play Store submission testing # ======================================================================
# TODO: Uncomment before going live with real ad traffic # signature = request.args.get('signature')
# key_id = request.args.get('key_id')
# custom_data_str = request.args.get('custom_data')
#
# # Google sends a verification ping with signature+key_id but no custom_data
# if not custom_data_str:
# return "OK", 200 # Verification ping from Google dashboard
#
# if not all([signature, key_id]):
# return "Missing parameters", 400
#
# raw_qs = request.query_string.decode("utf-8") # raw_qs = request.query_string.decode("utf-8")
# if not _verify_admob_signature(raw_qs, signature, key_id): # if not _verify_admob_signature(raw_qs, signature, key_id):
# print("[ADMOB] Rejected callback — invalid signature.") # print("[ADMOB] Rejected callback — invalid signature.")
# return "Forbidden", 403 # return "Forbidden", 403
# ======================================================================
custom_data = json.loads(custom_data_str) custom_data = json.loads(custom_data_str)
device_id = custom_data.get('device_id') device_id = custom_data.get('device_id')
@@ -453,13 +480,23 @@ def session_status():
# Bulletproof fallback: If server public key is missing, try fetching it right now # Bulletproof fallback: If server public key is missing, try fetching it right now
global SERVER_PUBKEY global SERVER_PUBKEY
if not SERVER_PUBKEY: if not SERVER_PUBKEY:
pubkey = run_cmd(f"wg show {WG_INTERFACE} public-key") # Same as init: must read from awg0 on the host, not Docker's wg0
pubkey = run_cmd("awg show awg0 public-key")
if pubkey: if pubkey:
SERVER_PUBKEY = pubkey SERVER_PUBKEY = pubkey
print(f"[WG] Dynamic Server Public Key cached: {SERVER_PUBKEY}") print(f"[WG] Dynamic Server Public Key cached from awg0: {SERVER_PUBKEY}")
else: else:
# Absolute fallback if docker exec is broken on this host # Absolute fallback if docker exec is broken on this host
SERVER_PUBKEY = SERVER_PUBKEY_FALLBACK or "YOUR_SERVER_PUBLIC_KEY_HERE" ########
######### 313131
#######
########
SERVER_PUBKEY = SERVER_PUBKEY_FALLBACK or "server key="
######
########
#########
##########
##########
stats = get_wireguard_stats() stats = get_wireguard_stats()
current_bytes = stats.get(session["ip"], {}).get("total_bytes", 0) current_bytes = stats.get(session["ip"], {}).get("total_bytes", 0)