2601.01 - Adding stealth mode
This commit is contained in:
1 parent
f90613da16
commit
469235194d
15 files changed
+24
-12
No files matched your search
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+6
-2
@@ -42,7 +42,10 @@ def _parse_args(argv=None):
|
|||||||
p.add_argument('--no-iptables', action='store_true',
|
p.add_argument('--no-iptables', action='store_true',
|
||||||
help='Skip iptables rule setup/teardown')
|
help='Skip iptables rule setup/teardown')
|
||||||
p.add_argument('-v', '--verbose', action='store_true',
|
p.add_argument('-v', '--verbose', action='store_true',
|
||||||
help='Print each connection to stdout')
|
help='Print each connection to stdout')
|
||||||
|
p.add_argument('--stealth', action='store_true',
|
||||||
|
help='Send no data on connections — close immediately, '
|
||||||
|
'still logging each connection')
|
||||||
p.add_argument('--admin-port', type=int, default=None, metavar='PORT',
|
p.add_argument('--admin-port', type=int, default=None, metavar='PORT',
|
||||||
help='Enable web admin interface on this port (default: disabled)')
|
help='Enable web admin interface on this port (default: disabled)')
|
||||||
p.add_argument('--admin-host', default='127.0.0.1', metavar='HOST',
|
p.add_argument('--admin-host', default='127.0.0.1', metavar='HOST',
|
||||||
@@ -177,7 +180,8 @@ def main(argv=None) -> int:
|
|||||||
try:
|
try:
|
||||||
bind_ip: Optional[str] = args.bind_ip or None
|
bind_ip: Optional[str] = args.bind_ip or None
|
||||||
tasks.append(asyncio.create_task(
|
tasks.append(asyncio.create_task(
|
||||||
run_server(cfg, log, bind_ip, args.port, args.verbose, stop_event, settings)
|
run_server(cfg, log, bind_ip, args.port, args.verbose, stop_event, settings,
|
||||||
|
stealth=args.stealth)
|
||||||
))
|
))
|
||||||
if args.admin_port:
|
if args.admin_port:
|
||||||
tasks.append(asyncio.create_task(
|
tasks.append(asyncio.create_task(
|
||||||
|
|||||||
+18
-10
@@ -38,6 +38,7 @@ async def _handle(
|
|||||||
log: Logger,
|
log: Logger,
|
||||||
verbose: bool,
|
verbose: bool,
|
||||||
settings: Settings,
|
settings: Settings,
|
||||||
|
stealth: bool = False,
|
||||||
) -> None:
|
) -> None:
|
||||||
sock = writer.get_extra_info('socket')
|
sock = writer.get_extra_info('socket')
|
||||||
peername = writer.get_extra_info('peername') or ('?.?.?.?', 0)
|
peername = writer.get_extra_info('peername') or ('?.?.?.?', 0)
|
||||||
@@ -49,19 +50,23 @@ async def _handle(
|
|||||||
sockname = writer.get_extra_info('sockname') or ('', 0)
|
sockname = writer.get_extra_info('sockname') or ('', 0)
|
||||||
original_port = sockname[1]
|
original_port = sockname[1]
|
||||||
|
|
||||||
banner = cfg.get_banner(original_port)
|
banner = b'' if stealth else cfg.get_banner(original_port)
|
||||||
|
|
||||||
if verbose:
|
if verbose:
|
||||||
print(
|
if stealth:
|
||||||
f"[conn] {src_ip}:{src_port} → port {original_port}"
|
print(f"[conn] {src_ip}:{src_port} → port {original_port} banner=(none, stealth)")
|
||||||
f" banner={banner[:32].hex()}{'…' if len(banner) > 32 else ''}"
|
else:
|
||||||
)
|
print(
|
||||||
|
f"[conn] {src_ip}:{src_port} → port {original_port}"
|
||||||
|
f" banner={banner[:32].hex()}{'…' if len(banner) > 32 else ''}"
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
await asyncio.sleep(random.uniform(settings.delay_min, settings.delay_max))
|
if not stealth:
|
||||||
if banner:
|
await asyncio.sleep(random.uniform(settings.delay_min, settings.delay_max))
|
||||||
writer.write(banner)
|
if banner:
|
||||||
await writer.drain()
|
writer.write(banner)
|
||||||
|
await writer.drain()
|
||||||
except (ConnectionResetError, BrokenPipeError):
|
except (ConnectionResetError, BrokenPipeError):
|
||||||
pass
|
pass
|
||||||
finally:
|
finally:
|
||||||
@@ -82,11 +87,12 @@ async def run_server(
|
|||||||
verbose: bool,
|
verbose: bool,
|
||||||
stop_event: asyncio.Event,
|
stop_event: asyncio.Event,
|
||||||
settings: Settings,
|
settings: Settings,
|
||||||
|
stealth: bool = False,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Start the asyncio TCP server and run until stop_event is set."""
|
"""Start the asyncio TCP server and run until stop_event is set."""
|
||||||
|
|
||||||
def handler(r, w):
|
def handler(r, w):
|
||||||
asyncio.create_task(_handle(r, w, cfg, log, verbose, settings))
|
asyncio.create_task(_handle(r, w, cfg, log, verbose, settings, stealth))
|
||||||
|
|
||||||
server = await asyncio.start_server(
|
server = await asyncio.start_server(
|
||||||
handler,
|
handler,
|
||||||
@@ -98,6 +104,8 @@ async def run_server(
|
|||||||
|
|
||||||
addrs = ', '.join(str(s.getsockname()) for s in server.sockets)
|
addrs = ', '.join(str(s.getsockname()) for s in server.sockets)
|
||||||
print(f"[portspoof] listening on {addrs}")
|
print(f"[portspoof] listening on {addrs}")
|
||||||
|
if stealth:
|
||||||
|
print("[portspoof] stealth mode: connections closed without sending data")
|
||||||
|
|
||||||
async with server:
|
async with server:
|
||||||
await stop_event.wait()
|
await stop_event.wait()
|
||||||
|
|||||||
Reference in new issue
Block a user