Skip to content

feat: implement TELNET protocol support with authentication and comma…#253

Merged
mariocandela merged 2 commits intomainfrom
add-telnet
Jan 24, 2026
Merged

feat: implement TELNET protocol support with authentication and comma…#253
mariocandela merged 2 commits intomainfrom
add-telnet

Conversation

@mariocandela
Copy link
Copy Markdown
Contributor

@mariocandela mariocandela commented Jan 24, 2026

…nd handling

All Submissions:

  • Have you followed the guidelines in our Contributing document?
  • Have you checked to ensure there aren't other open Pull Requests for the same update/change?

New Feature Submissions:

  1. Does your submission pass tests?
  2. Have you lint your code locally before submission?

Changes to Core Features:

  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you written new tests for your core changes, as applicable?
  • Have you successfully run tests with your changes locally?

Summary by CodeRabbit

  • New Features

    • Added Telnet protocol support with configurable command patterns, deterministic responses, authentication, and interactive session behavior.
  • Tests

    • Added comprehensive Telnet integration tests covering authentication, command responses, unknown commands, sequences, and prompt behavior.
  • Chores

    • CI updated to exclude Telnet from coverage filtering.
    • Metrics enhanced with Telnet event tracking (new counter) for observability.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Jan 24, 2026

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

Adds first-class Telnet protocol support: new TELNET strategy implementation, configs and integration tests, builder wiring, tracer instrumentation for Telnet events, and CI coverage exclusion for the new file.

Changes

Cohort / File(s) Summary
CI / Coverage
/.github/workflows/ci.yml
Expand coverage exclusions to include telnet.go.
Builder & Protocol Wiring
builder/builder.go
Import and wire the new TELNET strategy into protocol manager; handle "telnet" case.
Tracer Instrumentation
tracer/tracer.go, tracer/tracer_test.go
Add TELNET protocol constant, string mapping, Prometheus counter telnet_events_total, initialization and counter incrementing; update tests to account for new counter.
TELNET Strategy Implementation
protocols/strategies/TELNET/telnet.go
New TelnetStrategy with Init: TCP listener, minimal IAC negotiation, login prompt and password regex validation, interactive command loop, regex-based command matching, optional LLM invocation path, session history storage, and tracer event logging.
Service Configurations
configurations/services/telnet-23.yaml, integration_test/configurations/services/telnet-2300.yaml
New production and integration-test Telnet service configs: protocol, address, server metadata, command regex→handler mappings, passwordRegex, and timeout settings.
Integration Tests
integration_test/integration_test.go
Add telnetHoneypotHost field, readTelnetUntil helper, and six Telnet-focused tests covering auth, command responses, unknown commands, sequences, and prompt correctness; initialize Telnet test host in SetupSuite.

Sequence Diagram(s)

sequenceDiagram
    participant Client as Telnet Client
    participant Server as TelnetStrategy
    participant Tracer as Tracer
    participant History as HistoryStore
    participant LLM as LLM Handler

    Client->>Server: TCP connect
    Server->>Server: Perform IAC negotiation
    Server->>Client: Send login prompt
    Client->>Server: Send username/password
    Server->>Server: Validate password (regex)
    Server->>Tracer: Emit login event
    Server->>History: Create session record

    loop interactive commands
        Client->>Server: Send command line
        Server->>Server: Match command (regex)
        alt matched and LLM-eligible
            Server->>LLM: Invoke model for response
            LLM-->>Server: Return generated output
            Server->>Client: Send output
        else matched (static handler)
            Server->>Client: Send configured response
        else not matched
            Server->>Client: Send "command not found"
        end
        Server->>History: Append interaction
        Server->>Tracer: Emit interaction event
    end

    Client->>Server: Disconnect
    Server->>Tracer: Emit session end event
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

enhancement

Poem

🐰 I hopped into a telnet sea,

IAC waves tickled me,
Commands echoed, traces shone,
Histories stored, sessions grown—
A tiny hare in honeypot glee.

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description contains only the repository's template checklist with unchecked boxes and no substantive explanation of what was implemented or why. Fill in the template by checking applicable boxes and adding a detailed explanation of the TELNET implementation, changes made, and confirmation that tests pass and code is linted.
Docstring Coverage ⚠️ Warning Docstring coverage is 11.11% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main change: implementing TELNET protocol support with authentication and command handling, which is the primary focus of the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link
Copy Markdown

codecov bot commented Jan 24, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 81.76%. Comparing base (8a83355) to head (3f43b0f).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #253      +/-   ##
==========================================
+ Coverage   81.55%   81.76%   +0.20%     
==========================================
  Files           7        7              
  Lines         618      625       +7     
==========================================
+ Hits          504      511       +7     
  Misses         93       93              
  Partials       21       21              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@integration_test/integration_test.go`:
- Around line 45-68: Update the misleading comment on readTelnetUntil to remove
the "skipping IAC sequences" claim (or implement IAC filtering if intended), and
change the overflow behavior so that when fullResponse grows beyond 8192 bytes
the function returns an error instead of (fullResponse, nil); use a descriptive
error (e.g., via fmt.Errorf) that callers can assert on. Ensure you add the
"fmt" import if you create the error and keep the rest of readTelnetUntil (conn
*net.TCPConn, expected string) behavior the same.

In `@protocols/strategies/TELNET/telnet.go`:
- Around line 305-341: In readLine, rename the local identifier currently named
`byte` to e.g. `ch` to avoid shadowing the builtin, add proper error handling
for the two conn.Read calls used to skip IAC bytes (check and return the error
if any read fails), and replace the ad-hoc `i`/256 check with a proper
max-line-length guard (define a constant like maxLineLen and return an error if
line length exceeds it) so the `line` slice cannot grow unbounded; ensure all
conn.Read results are checked and propagate errors from read operations in the
readLine function.
- Around line 287-303: The function drainInitialInput currently clears the
connection deadline by calling conn.SetReadDeadline(time.Time{}), which disables
the configured session timeout; change drainInitialInput to preserve and restore
the session deadline (either by reading the current deadline before setting the
short 200ms read deadline and restoring it after draining, or by accepting the
configured deadlineSeconds and calling conn.SetDeadline(time.Now().Add(...))
when finished) so the configured deadlineTimeoutSeconds remains enforced for the
remainder of the session; update references to drainInitialInput accordingly.
🧹 Nitpick comments (4)
protocols/strategies/TELNET/telnet.go (3)

135-140: Consider not logging the PasswordRegex pattern in error messages.

The static analysis flagged this line. While logging the regex pattern (not actual passwords) is lower risk, it could reveal which passwords the honeypot accepts to anyone with log access. Consider logging a generic error without the pattern:

🛠️ Suggested fix
 	matched, err := regexp.MatchString(servConf.PasswordRegex, password)
 	if err != nil {
-		log.Errorf("error regex: %s, %s", servConf.PasswordRegex, err.Error())
+		log.Errorf("error matching password regex: %s", err.Error())
 		conn.Write([]byte("Login incorrect\r\n"))
 		return
 	}

278-285: negotiateTelnet ignores write errors.

If the writes fail, the function silently continues. Consider logging or returning errors to aid debugging connection issues.

🛠️ Suggested fix
-func negotiateTelnet(conn net.Conn) {
+func negotiateTelnet(conn net.Conn) error {
 	// Minimal telnet negotiation
-	conn.Write([]byte{IAC, WILL, ECHO})
-	conn.Write([]byte{IAC, WILL, SUPPRESS_GO_AHEAD})
+	if _, err := conn.Write([]byte{IAC, WILL, ECHO}); err != nil {
+		return err
+	}
+	if _, err := conn.Write([]byte{IAC, WILL, SUPPRESS_GO_AHEAD}); err != nil {
+		return err
+	}
+	return nil
 }

343-357: Remove the unused stripIAC function.

This function is defined but never called anywhere in the codebase and should be removed as dead code.

integration_test/integration_test.go (1)

295-577: Consider extracting a helper for Telnet authentication.

The authentication sequence (connect → login → password → prompt) is repeated across all six Telnet tests. Extracting this into a helper would reduce duplication and make tests more maintainable.

Example helper
// authenticateTelnet connects and authenticates, returning the connection ready for commands
func (suite *IntegrationTestSuite) authenticateTelnet(user, pass string) (*net.TCPConn, error) {
	tcpAddr, err := net.ResolveTCPAddr("tcp", suite.telnetHoneypotHost)
	if err != nil {
		return nil, err
	}

	conn, err := net.DialTCP("tcp", nil, tcpAddr)
	if err != nil {
		return nil, err
	}

	conn.SetDeadline(time.Now().Add(5 * time.Second))

	if _, err := readTelnetUntil(conn, "login:"); err != nil {
		conn.Close()
		return nil, err
	}

	if _, err := conn.Write([]byte(user + "\r\n")); err != nil {
		conn.Close()
		return nil, err
	}

	if _, err := readTelnetUntil(conn, "Password:"); err != nil {
		conn.Close()
		return nil, err
	}

	if _, err := conn.Write([]byte(pass + "\r\n")); err != nil {
		conn.Close()
		return nil, err
	}

	return conn, nil
}

Tests that need successful auth can use:

conn, err := suite.authenticateTelnet("root", "test")
suite.Require().NoError(err)
defer conn.Close()

response, err := readTelnetUntil(conn, "root@test-server:~$")
// ...

@mariocandela mariocandela merged commit c4b2a39 into main Jan 24, 2026
5 checks passed
@mariocandela mariocandela deleted the add-telnet branch January 24, 2026 22:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants