Skip to main content

MAXCONN

PyPI Python CI License: MIT

Português

Projeto criado por Marcos Max para ser uma biblioteca Python voltada a redes e infraestrutura.

A ideia do MAXCONN é juntar, aos poucos, as ferramentas que um engenheiro de redes ou DevOps usa no dia a dia para automatizar tarefas de rede: conexão em equipamentos, execução de comandos, leitura de saída, coleta de dados, validação, inventário e, mais adiante, módulos específicos para fornecedores.

O início do projeto é a camada de conexão. Hoje o MAXCONN já tem cliente SSH e Telnet feitos sobre sockets, sem usar Paramiko, Netmiko, Scrapli ou Telnetlib como cliente em runtime.

Pacote no PyPI: https://pypi.org/project/maxconn/

Exemplo:

import maxconn

with maxconn.connect(
    "192.0.2.10",
    protocol="ssh",
    username="admin",
    password="secret",
) as conn:
    result = conn.run("display version", prompt_markers=(">", "#"))
    print(result.text)

Instalação

Instalação para desenvolvimento:

git clone https://github.com/mmaxjr/maxconn
cd maxconn
pip install -e ".[dev]"
pytest -v
ruff check src tests

Instalação para uso normal:

pip install maxconn

Para usar SSH:

pip install "maxconn[ssh]"

Telnet não puxa dependências extras. SSH usa cryptography pelo extra ssh. Paramiko fica só nos testes, para subir um servidor SSH local e validar o cliente do MAXCONN contra uma implementação independente.

Versão atual em desenvolvimento: 0.1.8.

CLI básica:

maxconn --version
maxconn ping 192.0.2.1
maxconn scan 192.0.2.1 --ports 22,23,80,443
maxconn traceroute 8.8.8.8
maxconn mtr 8.8.8.8
maxconn mtr 8.8.8.8 --count 5 --interval 1
maxconn mtr 8.8.8.8 --rediscover-every 30
maxconn mtr 8.8.8.8 --count 5 --json
maxconn mtr 8.8.8.8 --count 5 --export mtr-report.txt --no-clear
maxconn sftp ls 192.0.2.10 /configs --username admin --password secret
maxconn sftp get 192.0.2.10 /remote/startup.cfg ./startup.cfg --username admin --password secret
maxconn sftp put 192.0.2.10 ./backup.cfg /remote/backup.cfg --username admin --password secret
maxconn sftp stat 192.0.2.10 /remote/startup.cfg --username admin --password secret
maxconn sftp mkdir 192.0.2.10 /remote/new-folder --username admin --password secret
maxconn sftp rm 192.0.2.10 /remote/old.cfg --username admin --password secret
maxconn sftp rename 192.0.2.10 /remote/a.cfg /remote/b.cfg --username admin --password secret
maxconn doctor
maxconn snmp get 192.0.2.1 1.3.6.1.2.1.1.5.0 --community public
maxconn snmp walk 192.0.2.1 1.3.6.1.2.1.1 --community public
maxconn ssh 192.0.2.10 --username admin --password secret --command "show version"
maxconn telnet 192.0.2.20 --username admin --password secret --command "show status"

Uso Básico

Telnet:

import maxconn

with maxconn.connect(
    "192.0.2.20",
    protocol="telnet",
    username="admin",
    password="secret",
) as conn:
    result = conn.run("show status", prompt_markers=(">", "#"))
    print(result.text)

SSH:

import maxconn

with maxconn.connect(
    "192.0.2.30",
    protocol="ssh",
    username="admin",
    password="secret",
) as conn:
    result = conn.run("show version", prompt_markers=(">", "#"))
    print(result.text)

Para uso mais direto, Connection.send(), Connection.recv(), Connection.read_until() e Connection.send_command() continuam disponíveis.

Resultado de Comando

Connection.run() retorna um resultado com campos úteis:

result = conn.run("display version", prompt_markers=(">", "#"))

print(result.command)
print(result.text)
print(result.bytes)
print(result.elapsed)
print(result.exit_status)
print(result.ok)

result.ok é verdadeiro quando exit_status é None ou 0. Em sessões CLI interativas, como Telnet e shell SSH, geralmente não existe status de saída, então None é esperado.

Expect

Para automação guiada por prompt, use ExpectSession diretamente:

from maxconn.automation import ExpectSession, PromptProfile

expect = ExpectSession(conn, prompt_markers=PromptProfile.CISCO)
output = expect.run("show running-config", timeout=20.0)

ExpectSession faz o básico que uma CLI de equipamento costuma precisar:

  • espera por prompts
  • remove eco do comando
  • responde paginação simples, como --More--
  • inclui a saída parcial quando ocorre timeout
  • responde confirmações simples, como [Y/N]

Sessões e Ping

SessionManager controla conexões nomeadas:

import maxconn

manager = maxconn.SessionManager(defaults={"protocol": "ssh", "username": "admin"})
conn = manager.connect("olt-01", "192.0.2.10", password="secret")
result = conn.run("display version", prompt_markers=(">", "#"))
manager.close_all()

Ping básico:

import maxconn

result = maxconn.ping("192.0.2.1")
print(result.reachable)

Scanner TCP:

import maxconn

for result in maxconn.scan("192.0.2.1", ports=[22, 23, 80, 443]):
    print(result.port, "open" if result.open else "closed")

Traceroute e mini MTR:

import maxconn

trace = maxconn.traceroute("8.8.8.8")
for hop in trace.hops:
    print(hop.hop, hop.address)

report = maxconn.mtr("8.8.8.8", count=5)
print(report.loss_percent, report.avg)

No terminal, maxconn mtr HOST roda continuamente e atualiza uma tabela por hop. Use Ctrl+C para parar. Para uma execução limitada, informe --count. Saltos que não respondem aparecem como No response from host, para preservar o caminho sem misturar o marcador interno * na tabela. Por padrão a rota é descoberta uma vez e os hops conhecidos são medidos a cada rodada, o que deixa a atualização mais parecida com WinMTR. Em redes com muitos saltos silenciosos, aumente --trace-timeout. Para redescobrir a rota de tempos em tempos, use --rediscover-every N. Para automação e relatórios, use --json, --export caminho.txt e --no-clear.

HTTP e FTP

HTTP/HTTPS básico:

from maxconn.protocol.http import HTTPClient

response = HTTPClient(timeout=5.0).get("https://example.com")
print(response.status_code)
print(response.text)

FTP básico:

from maxconn.protocol.ftp import FTPClient

with FTPClient.connect(
    "192.0.2.40",
    username="user",
    password="secret",
) as ftp:
    print(ftp.list())
    data = ftp.download("backup.cfg")

SFTP inicial:

import maxconn

sftp = maxconn.connect_sftp(
    "192.0.2.40",
    username="user",
    password="secret",
)
try:
    print(sftp.listdir("/configs"))
    print(sftp.stat("/configs/startup.cfg"))
    sftp.download("/configs/startup.cfg", "startup.cfg")
    sftp.upload("backup.cfg", "/configs/backup.cfg")
    sftp.mkdir("/configs/archive")
    sftp.rename("/configs/backup.cfg", "/configs/archive/backup.cfg")
    sftp.remove("/configs/archive/old.cfg")
finally:
    sftp.close()

SNMP v2c básico:

from maxconn.protocol.snmp import SNMPClient

snmp = SNMPClient("192.0.2.1", community="public")
hostname = snmp.get("1.3.6.1.2.1.1.5.0")
print(hostname.value)

for item in snmp.walk("1.3.6.1.2.1.1"):
    print(item.oid, item.value)

Timeouts

connect() aceita timeouts separados:

conn = maxconn.connect(
    "192.0.2.30",
    protocol="ssh",
    username="admin",
    password="secret",
    connect_timeout=5.0,
    auth_timeout=10.0,
    command_timeout=5.0,
    prompt_timeout=10.0,
)

O argumento antigo timeout= continua funcionando. Quando connect_timeout ou auth_timeout não são informados, timeout= é usado como padrão.

Logging

A execução de comandos registra eventos pelo logger maxconn.audit:

import logging

logging.basicConfig(level=logging.INFO)

Trechos sensíveis com palavras como password, secret, token ou key são redigidos antes de ir para o log.

Erros

Use a hierarquia de exceções do projeto:

import maxconn

try:
    with maxconn.connect(
        "192.0.2.30",
        protocol="ssh",
        username="admin",
        password="bad-password",
    ) as conn:
        print(conn.run("show status", prompt_markers=(">", "#")).text)
except maxconn.AuthenticationError:
    print("Login failed")
except maxconn.ConnectionTimeoutError:
    print("Connection timed out")
except maxconn.ProtocolError as exc:
    print(f"Protocol problem: {exc}")
except maxconn.MaxConnError as exc:
    print(f"maxconn error: {exc}")

Direção do Projeto

  • Não transformar o projeto em wrapper de Paramiko, Netmiko, Scrapli ou Telnetlib.
  • Manter dependências opcionais atrás de extras.
  • Deixar bytes crus disponíveis para quem precisa.
  • Dar uma API simples para o caso comum.
  • Testar com servidores locais de Telnet e SSH sempre que fizer sentido.
  • Publicar novas versões no PyPI por tag, usando GitHub Actions e Trusted Publishing.

English

Project created by Marcos Max as a Python library for networking and infrastructure work.

MAXCONN is meant to grow into a practical toolkit for network engineers and DevOps engineers who automate network tasks: connecting to devices, running commands, reading output, collecting data, validating state, building inventory, and later adding vendor-specific modules.

The project starts with the connection layer. Today MAXCONN has SSH and Telnet clients built on top of sockets, without using Paramiko, Netmiko, Scrapli, or Telnetlib as runtime clients.

Package on PyPI: https://pypi.org/project/maxconn/

Example:

import maxconn

with maxconn.connect(
    "192.0.2.10",
    protocol="ssh",
    username="admin",
    password="secret",
) as conn:
    result = conn.run("display version", prompt_markers=(">", "#"))
    print(result.text)

Installation

Development install:

git clone https://github.com/mmaxjr/maxconn
cd maxconn
pip install -e ".[dev]"
pytest -v
ruff check src tests

Regular install:

pip install maxconn

For SSH:

pip install "maxconn[ssh]"

Telnet does not pull extra runtime dependencies. SSH uses cryptography through the ssh extra. Paramiko is test-only and is used to run a local SSH server for integration tests.

Current development version: 0.1.8.

Basic CLI:

maxconn --version
maxconn ping 192.0.2.1
maxconn scan 192.0.2.1 --ports 22,23,80,443
maxconn traceroute 8.8.8.8
maxconn mtr 8.8.8.8
maxconn mtr 8.8.8.8 --count 5 --interval 1
maxconn mtr 8.8.8.8 --rediscover-every 30
maxconn mtr 8.8.8.8 --count 5 --json
maxconn mtr 8.8.8.8 --count 5 --export mtr-report.txt --no-clear
maxconn sftp ls 192.0.2.10 /configs --username admin --password secret
maxconn sftp get 192.0.2.10 /remote/startup.cfg ./startup.cfg --username admin --password secret
maxconn sftp put 192.0.2.10 ./backup.cfg /remote/backup.cfg --username admin --password secret
maxconn sftp stat 192.0.2.10 /remote/startup.cfg --username admin --password secret
maxconn sftp mkdir 192.0.2.10 /remote/new-folder --username admin --password secret
maxconn sftp rm 192.0.2.10 /remote/old.cfg --username admin --password secret
maxconn sftp rename 192.0.2.10 /remote/a.cfg /remote/b.cfg --username admin --password secret
maxconn doctor
maxconn snmp get 192.0.2.1 1.3.6.1.2.1.1.5.0 --community public
maxconn snmp walk 192.0.2.1 1.3.6.1.2.1.1 --community public
maxconn ssh 192.0.2.10 --username admin --password secret --command "show version"
maxconn telnet 192.0.2.20 --username admin --password secret --command "show status"

Basic Usage

Telnet:

import maxconn

with maxconn.connect(
    "192.0.2.20",
    protocol="telnet",
    username="admin",
    password="secret",
) as conn:
    result = conn.run("show status", prompt_markers=(">", "#"))
    print(result.text)

SSH:

import maxconn

with maxconn.connect(
    "192.0.2.30",
    protocol="ssh",
    username="admin",
    password="secret",
) as conn:
    result = conn.run("show version", prompt_markers=(">", "#"))
    print(result.text)

For lower-level use, Connection.send(), Connection.recv(), Connection.read_until(), and Connection.send_command() are still available.

Command Result

Connection.run() returns a result object:

result = conn.run("display version", prompt_markers=(">", "#"))

print(result.command)
print(result.text)
print(result.bytes)
print(result.elapsed)
print(result.exit_status)
print(result.ok)

result.ok is true when exit_status is None or 0. Interactive CLI sessions, such as Telnet and shell-style SSH, usually do not provide an exit status, so None is expected.

Expect

For prompt-based automation, use ExpectSession directly:

from maxconn.automation import ExpectSession, PromptProfile

expect = ExpectSession(conn, prompt_markers=PromptProfile.CISCO)
output = expect.run("show running-config", timeout=20.0)

ExpectSession handles the common parts of a network device CLI:

  • waits for prompts
  • strips command echo
  • answers simple pagination markers such as --More--
  • includes partial output in timeout errors
  • answers simple confirmation prompts such as [Y/N]

Sessions and Ping

SessionManager controls named connections:

import maxconn

manager = maxconn.SessionManager(defaults={"protocol": "ssh", "username": "admin"})
conn = manager.connect("olt-01", "192.0.2.10", password="secret")
result = conn.run("display version", prompt_markers=(">", "#"))
manager.close_all()

Basic ping:

import maxconn

result = maxconn.ping("192.0.2.1")
print(result.reachable)

TCP scan:

import maxconn

for result in maxconn.scan("192.0.2.1", ports=[22, 23, 80, 443]):
    print(result.port, "open" if result.open else "closed")

Traceroute and mini MTR:

import maxconn

trace = maxconn.traceroute("8.8.8.8")
for hop in trace.hops:
    print(hop.hop, hop.address)

report = maxconn.mtr("8.8.8.8", count=5)
print(report.loss_percent, report.avg)

In the terminal, maxconn mtr HOST runs continuously and refreshes a table per hop. Stop it with Ctrl+C. For a bounded run, pass --count. Hops that do not answer are shown as No response from host, so the path is not hidden and the internal * marker does not leak into the table. By default the route is discovered once and known hops are measured every round, which makes refreshes closer to WinMTR. On networks with many silent hops, increase --trace-timeout. To refresh the route periodically, use --rediscover-every N. For automation and reports, use --json, --export path.txt, and --no-clear.

HTTP and FTP

Basic HTTP/HTTPS:

from maxconn.protocol.http import HTTPClient

response = HTTPClient(timeout=5.0).get("https://example.com")
print(response.status_code)
print(response.text)

Basic FTP:

from maxconn.protocol.ftp import FTPClient

with FTPClient.connect(
    "192.0.2.40",
    username="user",
    password="secret",
) as ftp:
    print(ftp.list())
    data = ftp.download("backup.cfg")

Initial SFTP:

import maxconn

sftp = maxconn.connect_sftp(
    "192.0.2.40",
    username="user",
    password="secret",
)
try:
    print(sftp.listdir("/configs"))
    print(sftp.stat("/configs/startup.cfg"))
    sftp.download("/configs/startup.cfg", "startup.cfg")
    sftp.upload("backup.cfg", "/configs/backup.cfg")
    sftp.mkdir("/configs/archive")
    sftp.rename("/configs/backup.cfg", "/configs/archive/backup.cfg")
    sftp.remove("/configs/archive/old.cfg")
finally:
    sftp.close()

Basic SNMP v2c:

from maxconn.protocol.snmp import SNMPClient

snmp = SNMPClient("192.0.2.1", community="public")
hostname = snmp.get("1.3.6.1.2.1.1.5.0")
print(hostname.value)

for item in snmp.walk("1.3.6.1.2.1.1"):
    print(item.oid, item.value)

Timeouts

connect() accepts separate timeouts:

conn = maxconn.connect(
    "192.0.2.30",
    protocol="ssh",
    username="admin",
    password="secret",
    connect_timeout=5.0,
    auth_timeout=10.0,
    command_timeout=5.0,
    prompt_timeout=10.0,
)

The older timeout= argument still works. When connect_timeout or auth_timeout is not provided, timeout= is used as the default.

Logging

Command execution writes audit events through the maxconn.audit logger:

import logging

logging.basicConfig(level=logging.INFO)

Command fragments with words such as password, secret, token, or key are redacted before logging.

Errors

Use the project exception hierarchy:

import maxconn

try:
    with maxconn.connect(
        "192.0.2.30",
        protocol="ssh",
        username="admin",
        password="bad-password",
    ) as conn:
        print(conn.run("show status", prompt_markers=(">", "#")).text)
except maxconn.AuthenticationError:
    print("Login failed")
except maxconn.ConnectionTimeoutError:
    print("Connection timed out")
except maxconn.ProtocolError as exc:
    print(f"Protocol problem: {exc}")
except maxconn.MaxConnError as exc:
    print(f"maxconn error: {exc}")

Project Direction

  • Do not turn the project into a wrapper around Paramiko, Netmiko, Scrapli, or Telnetlib.
  • Keep optional dependencies behind extras.
  • Keep raw bytes available for code that needs them.
  • Keep the common API simple.
  • Test against local Telnet and SSH servers when it makes sense.
  • Publish new versions to PyPI by tag, using GitHub Actions and Trusted Publishing.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

maxconn-0.1.8.tar.gz (55.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

maxconn-0.1.8-py3-none-any.whl (47.7 kB view details)

Uploaded Python 3

File details

Details for the file maxconn-0.1.8.tar.gz.

File metadata

  • Download URL: maxconn-0.1.8.tar.gz
  • Upload date:
  • Size: 55.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for maxconn-0.1.8.tar.gz
Algorithm Hash digest
SHA256 bd34dd1dd484df95aaaa98a13ab8b3904f1e54577e127dd90cfa93b020061544
MD5 7cfc778530c789da08862d0d9164eeea
BLAKE2b-256 e58e7c5b11a4215ac951167fd7b34dea874ba015420a3e1ad7e0e19e45a4120c

See more details on using hashes here.

Provenance

The following attestation bundles were made for maxconn-0.1.8.tar.gz:

Publisher: publish.yml on mmaxjr/maxconn

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file maxconn-0.1.8-py3-none-any.whl.

File metadata

  • Download URL: maxconn-0.1.8-py3-none-any.whl
  • Upload date:
  • Size: 47.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for maxconn-0.1.8-py3-none-any.whl
Algorithm Hash digest
SHA256 961e2b7247c4cf850facb8565bba66ab26c8fbc72e8a074acc910d3177165109
MD5 d89574369337b39114c8abfafc6ca0d7
BLAKE2b-256 360dbffac950506ed2cf42b295b29f4ab67c5af25190031651381e0a11386687

See more details on using hashes here.

Provenance

The following attestation bundles were made for maxconn-0.1.8-py3-none-any.whl:

Publisher: publish.yml on mmaxjr/maxconn

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.3.2

2 files

0.3.1

2 files

0.3.0

2 files

0.2.0

2 files

0.1.19

2 files

0.1.18

2 files

0.1.17

2 files

0.1.16

2 files

0.1.15

2 files

0.1.14

2 files

0.1.13

2 files

0.1.12

2 files

0.1.11

2 files

0.1.10

2 files

0.1.9

2 files

This release

0.1.8 This release

2 files

0.1.7

2 files

0.1.6

2 files

0.1.5

2 files

0.1.4

2 files

0.1.3

2 files

0.1.2

2 files

0.1.1

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page