update generate_bug_report.py
This commit is contained in:
parent
8a5197cf04
commit
4f798f145b
2 changed files with 83 additions and 23 deletions
16
README.md
16
README.md
|
@ -19,12 +19,12 @@ Verify python is version 3.6-8
|
||||||
python --version
|
python --version
|
||||||
```
|
```
|
||||||
|
|
||||||
Installation for normal usage
|
#### Installation for normal usage
|
||||||
```
|
```
|
||||||
pip install aioupnp
|
pip install aioupnp
|
||||||
```
|
```
|
||||||
|
|
||||||
Installation for development
|
#### Installation for development
|
||||||
```
|
```
|
||||||
git clone https://github.com/lbryio/aioupnp.git
|
git clone https://github.com/lbryio/aioupnp.git
|
||||||
cd aioupnp
|
cd aioupnp
|
||||||
|
@ -111,14 +111,18 @@ By default, the network device will be automatically discovered. The interface m
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
#### Debug logging
|
#### Debug logging
|
||||||
To enable verbose debug logging, add the `--debug_logging` argument before the command
|
To enable verbose debug logging, add the `--debug_logging` argument before the command being run
|
||||||
|
|
||||||
aioupnp --debug_logging m_search
|
aioupnp --debug_logging m_search
|
||||||
|
|
||||||
#### It really doesn't work
|
#### Is it turned on?
|
||||||
If aioupnp doesn't work with a device, a debugging report can be collected with `aioupnp gather_debug_info`.
|
Check that UPnP is turned on in the web gui for your router.
|
||||||
|
|
||||||
This will attempt to discover the UPnP gateway, and then perform a functionality check where it will request the external address and existing port mappings before attempting to make and remove a port mapping. The final result is the zipped packet dump of these attempts, which allows writing tests replaying it.
|
#### It really doesn't work
|
||||||
|
|
||||||
|
If it always fails with an m-search error, or the UPnP device is found but making a port mapping or getting the external address fails, a bug report can be generated and automatically sent using the `generate_bug_report.py` script. This script will run a packet capture while attempting to find the device and add/remove a mapping using `miniupnpc` and `aioupnp`. Once complete, it will submit a bug report of the packets sent/recieved by aioupnp/miniupnpc.
|
||||||
|
|
||||||
|
To run the bug report script, first `pip install certifi aiohttp miniupnpc`. You'll also need `aioupnp` installed. Then generate and send the bug report with `sudo /full/path/to/your/python generate_bug_report.py`.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
import socket
|
import socket
|
||||||
import typing
|
|
||||||
import ctypes
|
import ctypes
|
||||||
import contextlib
|
import contextlib
|
||||||
import struct
|
import struct
|
||||||
|
@ -9,14 +9,22 @@ import enum
|
||||||
import re
|
import re
|
||||||
import time
|
import time
|
||||||
import base64
|
import base64
|
||||||
|
import ssl
|
||||||
|
import asyncio
|
||||||
|
import codecs
|
||||||
|
import typing
|
||||||
|
import json
|
||||||
from ctypes import c_char, c_short
|
from ctypes import c_char, c_short
|
||||||
from typing import Tuple
|
from typing import Tuple
|
||||||
import asyncio
|
import aioupnp
|
||||||
from aioupnp.upnp import UPnP, UPnPError, get_gateway_and_lan_addresses
|
from aioupnp.upnp import UPnP, UPnPError, get_gateway_and_lan_addresses
|
||||||
from aioupnp.constants import SSDP_IP_ADDRESS
|
from aioupnp.constants import SSDP_IP_ADDRESS
|
||||||
|
import certifi
|
||||||
|
import aiohttp
|
||||||
import miniupnpc
|
import miniupnpc
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
_IFF_PROMISC = 0x0100
|
_IFF_PROMISC = 0x0100
|
||||||
_SIOCGIFFLAGS = 0x8913 # get the active flags
|
_SIOCGIFFLAGS = 0x8913 # get the active flags
|
||||||
_SIOCSIFFLAGS = 0x8914 # set the active flags
|
_SIOCSIFFLAGS = 0x8914 # set the active flags
|
||||||
|
@ -365,34 +373,44 @@ async def main():
|
||||||
|
|
||||||
def discover_aioupnp():
|
def discover_aioupnp():
|
||||||
async def _discover():
|
async def _discover():
|
||||||
print("test aioupnp")
|
print("testing aioupnp")
|
||||||
try:
|
try:
|
||||||
u = await UPnP.discover()
|
u = await UPnP.discover()
|
||||||
|
print("successfully detected router with aioupnp")
|
||||||
try:
|
try:
|
||||||
await u.get_external_ip()
|
await u.get_external_ip()
|
||||||
|
print("successfully detected external ip with aioupnp")
|
||||||
except UPnPError:
|
except UPnPError:
|
||||||
pass
|
print("failed to detect external ip with aioupnp")
|
||||||
try:
|
try:
|
||||||
await u.get_redirects()
|
await u.get_redirects()
|
||||||
|
print("successfully detected redirects with aioupnp")
|
||||||
except UPnPError:
|
except UPnPError:
|
||||||
pass
|
print("failed to get redirects with aioupnp")
|
||||||
try:
|
try:
|
||||||
external_port = await u.get_next_mapping(1234, 'TCP', 'aioupnp testing')
|
external_port = await u.get_next_mapping(1234, 'TCP', 'aioupnp testing')
|
||||||
|
print("successfully set redirect with aioupnp")
|
||||||
except UPnPError:
|
except UPnPError:
|
||||||
|
print("failed to set redirect with aioupnp")
|
||||||
external_port = None
|
external_port = None
|
||||||
try:
|
try:
|
||||||
await u.get_redirects()
|
await u.get_redirects()
|
||||||
|
print("successfully detected redirects with aioupnp")
|
||||||
except UPnPError:
|
except UPnPError:
|
||||||
pass
|
print("failed to get redirects with aioupnp")
|
||||||
if external_port:
|
if external_port:
|
||||||
try:
|
try:
|
||||||
|
print("successfully removed redirect with aioupnp")
|
||||||
await u.delete_port_mapping(external_port, 'TCP')
|
await u.delete_port_mapping(external_port, 'TCP')
|
||||||
except UPnPError:
|
except UPnPError:
|
||||||
pass
|
print("failed to delete redirect with aioupnp")
|
||||||
try:
|
try:
|
||||||
await u.get_redirects()
|
await u.get_redirects()
|
||||||
|
print("successfully detected redirects with aioupnp")
|
||||||
except UPnPError:
|
except UPnPError:
|
||||||
pass
|
print("failed to get redirects with aioupnp")
|
||||||
|
except UPnPError:
|
||||||
|
print("failed to discover router with aioupnp")
|
||||||
finally:
|
finally:
|
||||||
print("done with aioupnp test")
|
print("done with aioupnp test")
|
||||||
asyncio.create_task(_discover())
|
asyncio.create_task(_discover())
|
||||||
|
@ -402,22 +420,28 @@ async def main():
|
||||||
try:
|
try:
|
||||||
u = miniupnpc.UPnP()
|
u = miniupnpc.UPnP()
|
||||||
except:
|
except:
|
||||||
|
print("failed to create upnp object with miniupnpc")
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
u.discover()
|
u.discover()
|
||||||
except:
|
except:
|
||||||
|
print("failed to detect router with miniupnpc")
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
u.selectigd()
|
u.selectigd()
|
||||||
|
print("successfully detected router with miniupnpc")
|
||||||
except:
|
except:
|
||||||
|
print("failed to detect router with miniupnpc")
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
u.externalipaddress()
|
u.externalipaddress()
|
||||||
|
print("successfully detected external ip with miniupnpc")
|
||||||
except:
|
except:
|
||||||
|
print("failed to detect external ip with miniupnpc")
|
||||||
return
|
return
|
||||||
|
|
||||||
async def _discover():
|
async def _discover():
|
||||||
print("test miniupnpc")
|
print("testing miniupnpc")
|
||||||
try:
|
try:
|
||||||
await loop.run_in_executor(None, _miniupnpc_discover)
|
await loop.run_in_executor(None, _miniupnpc_discover)
|
||||||
finally:
|
finally:
|
||||||
|
@ -426,10 +450,10 @@ async def main():
|
||||||
|
|
||||||
asyncio.create_task(_discover())
|
asyncio.create_task(_discover())
|
||||||
|
|
||||||
loop.call_later(2, discover_aioupnp)
|
loop.call_later(0, discover_aioupnp)
|
||||||
loop.call_later(10, discover_miniupnpc)
|
loop.call_later(8, discover_miniupnpc)
|
||||||
start = time.perf_counter()
|
start = time.perf_counter()
|
||||||
f = open("upnp_packet_cap.txt", "w")
|
packets = []
|
||||||
try:
|
try:
|
||||||
async for (ts, ipv4_packet) in sniff_ipv4([
|
async for (ts, ipv4_packet) in sniff_ipv4([
|
||||||
make_filter(l3_protocol=Layer3.UDP, src=SSDP_IP_ADDRESS),
|
make_filter(l3_protocol=Layer3.UDP, src=SSDP_IP_ADDRESS),
|
||||||
|
@ -438,14 +462,46 @@ async def main():
|
||||||
make_filter(l3_protocol=Layer3.UDP, src=gateway, dst=lan),
|
make_filter(l3_protocol=Layer3.UDP, src=gateway, dst=lan),
|
||||||
make_filter(l3_protocol=Layer3.TCP, src=lan, dst=gateway),
|
make_filter(l3_protocol=Layer3.TCP, src=lan, dst=gateway),
|
||||||
make_filter(l3_protocol=Layer3.TCP, src=gateway, dst=lan)], done):
|
make_filter(l3_protocol=Layer3.TCP, src=gateway, dst=lan)], done):
|
||||||
f.write(f"{time.perf_counter() - start},{ipv4_packet.packet_type.name},{ipv4_packet.source},{ipv4_packet.destination},{base64.b64encode(ipv4_packet.data).decode()}\n")
|
packets.append(
|
||||||
print(ts, ipv4_packet)
|
(time.perf_counter() - start, ipv4_packet.packet_type.name,
|
||||||
print(ipv4_packet.printable_data)
|
ipv4_packet.source, ipv4_packet.destination, base64.b64encode(ipv4_packet.data).decode())
|
||||||
print()
|
)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
print("stopping")
|
print("stopping")
|
||||||
finally:
|
finally:
|
||||||
f.close()
|
print("Sending bug report")
|
||||||
|
ssl_ctx = ssl.create_default_context(
|
||||||
|
purpose=ssl.Purpose.CLIENT_AUTH, capath=certifi.where()
|
||||||
|
)
|
||||||
|
auth = aiohttp.BasicAuth(
|
||||||
|
base64.b64decode(codecs.encode('nJ1bp3yfoxLlG3MaA3WHrwA1pIWInx9CpyOYA3S2ZKp=', 'rot_13')).decode(), ''
|
||||||
|
)
|
||||||
|
report_id = base64.b64encode(os.urandom(16)).decode()
|
||||||
|
async with aiohttp.ClientSession() as session:
|
||||||
|
for i, (ts, direction, source, destination, packet) in enumerate(packets):
|
||||||
|
post = {
|
||||||
|
'userId': report_id,
|
||||||
|
'event': 'aioupnp bug report',
|
||||||
|
'context': {
|
||||||
|
'library': {
|
||||||
|
'name': 'aioupnp',
|
||||||
|
'version': aioupnp.__version__
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'properties': {
|
||||||
|
'sequence': i,
|
||||||
|
'ts': ts,
|
||||||
|
'direction': direction,
|
||||||
|
'source': source,
|
||||||
|
'destination': destination,
|
||||||
|
'packet': base64.b64encode(json.dumps(packet).encode()).decode()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
async with session.request(method='POST', url='https://api.segment.io/v1/track',
|
||||||
|
headers={'Connection': 'Close'}, auth=auth, json=post, ssl=ssl_ctx):
|
||||||
|
sys.stdout.write(f"\r{'.' * i}")
|
||||||
|
sys.stdout.write("\n")
|
||||||
|
print("Successfully sent bug report, thanks for your contribution!")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
Loading…
Reference in a new issue