This is an automated email from the ASF dual-hosted git repository.

FreeAndNil pushed a commit to branch Feature/318-telnet-default
in repository https://gitbox.apache.org/repos/asf/logging-log4net.git

commit 7ddebdd22de162cc9247ba5407435cae6cbba432
Author: Jan Friedrich <[email protected]>
AuthorDate: Fri Sep 4 07:36:25 2026 +0200

    listen on loopback by default in TelnetAppender #318
    
    - The appender streams the rendered log to any client that connects, with no
      authentication and no encryption, and defaulted to every interface on 
port 23.
    - It now defaults to 127.0.0.1. Watching from another machine is opt-in: set
      listenAddress to 0.0.0.0 or ::. Every documented example already used 
loopback.
    - SocketHandler(port, sendTimeoutMillis) defaults the same way.
    
    Deliberate default flip: a deployment relying on the implicit all-interfaces
    bind loses remote access until it sets listenAddress.
    
    audit da18b6fd-f012
---
 .../3.5.0/318-telnet-loopback-default.xml          | 13 ++++++++++++
 src/log4net.Tests/Appender/TelnetAppenderTest.cs   | 17 +++++++++++----
 src/log4net/Appender/TelnetAppender.cs             | 24 ++++++++++++----------
 .../configuration/appenders/telnetappender.adoc    | 20 ++++++++++--------
 4 files changed, 50 insertions(+), 24 deletions(-)

diff --git a/src/changelog/3.5.0/318-telnet-loopback-default.xml 
b/src/changelog/3.5.0/318-telnet-loopback-default.xml
new file mode 100644
index 00000000..2361c159
--- /dev/null
+++ b/src/changelog/3.5.0/318-telnet-loopback-default.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<entry xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+       xmlns="https://logging.apache.org/xml/ns";
+       xsi:schemaLocation="https://logging.apache.org/xml/ns 
https://logging.apache.org/xml/ns/log4j-changelog-0.xsd";
+       type="changed">
+  <issue id="318" link="https://github.com/apache/logging-log4net/pull/318"/>
+  <description format="asciidoc">`TelnetAppender` now listens on `127.0.0.1` 
by default instead of every
+  interface. The stream is unauthenticated and unencrypted, so any host that 
could reach the port
+  could read the application's log, and every documented example already used 
loopback. Watching the
+  log from another machine is now opt-in: set `listenAddress` to `0.0.0.0` or 
`::` to restore the old
+  behaviour. The `SocketHandler(port, sendTimeoutMillis)` constructor defaults 
the same way (audit
+  da18b6fd-f012, implemented by @FreeAndNil)</description>
+</entry>
diff --git a/src/log4net.Tests/Appender/TelnetAppenderTest.cs 
b/src/log4net.Tests/Appender/TelnetAppenderTest.cs
index c0df92b4..9b0bb3b2 100644
--- a/src/log4net.Tests/Appender/TelnetAppenderTest.cs
+++ b/src/log4net.Tests/Appender/TelnetAppenderTest.cs
@@ -239,12 +239,21 @@ public void 
SendTimeoutMillisRejectsNegativeValuesButAllowsZero()
   }
 
   /// <summary>
-  /// The appender accepts connections on every interface unless told 
otherwise, which is the
-  /// behaviour it has always had.
+  /// The stream is unauthenticated, so an appender nobody configured an 
address for must not be
+  /// reachable from another machine.
   /// </summary>
   [Test]
-  public void ListenAddressDefaultsToEveryInterface()
-    => Assert.That(new TelnetAppender().ListenAddress, 
Is.EqualTo(IPAddress.Any));
+  public void ListenAddressDefaultsToLoopback()
+    => Assert.That(new TelnetAppender().ListenAddress, 
Is.EqualTo(IPAddress.Loopback));
+
+  /// <summary>
+  /// Remote monitoring is still available, it just has to be asked for.
+  /// </summary>
+  [TestCase("::", TestName = "EveryIPv6InterfaceCanBeAskedFor")]
+  [TestCase("0.0.0.0", TestName = "EveryIPv4InterfaceCanBeAskedFor")]
+  public void EveryInterfaceCanBeAskedFor(string address)
+    => Assert.That(new TelnetAppender { ListenAddress = 
IPAddress.Parse(address) }.ListenAddress,
+      Is.EqualTo(IPAddress.Parse(address)));
 
   /// <summary>
   /// Binding to the loopback address has to keep the port unreachable from 
other machines, which
diff --git a/src/log4net/Appender/TelnetAppender.cs 
b/src/log4net/Appender/TelnetAppender.cs
index 903cd0d5..b38a9373 100644
--- a/src/log4net/Appender/TelnetAppender.cs
+++ b/src/log4net/Appender/TelnetAppender.cs
@@ -37,10 +37,11 @@ namespace log4net.Appender;
 /// <para>
 /// The TelnetAppender accepts socket connections and streams logging messages 
back to the client.
 /// The output is provided in a telnet-friendly way so that a log can be 
monitored over a TCP/IP socket.
-/// This allows simple remote monitoring of application logging.
 /// </para>
 /// <para>
-/// The default <see cref="Port"/> is 23 (the telnet port).
+/// The default <see cref="Port"/> is 23 (the telnet port) and the default
+/// <see cref="ListenAddress"/> is <see cref="IPAddress.Loopback"/>, so 
monitoring from another
+/// machine has to be turned on deliberately.
 /// </para>
 /// <para>
 /// This appender is a diagnostic tool for trusted networks. As with any other 
appender
@@ -57,20 +58,20 @@ public class TelnetAppender : AppenderSkeleton
   private SocketHandler? _handler;
   private int _listeningPort = 23;
   private int _sendTimeoutMillis = 5_000;
-  private IPAddress _listenAddress = IPAddress.Any;
+  private IPAddress _listenAddress = IPAddress.Loopback;
 
   /// <summary>
   /// Gets or sets the address to listen on.
   /// </summary>
   /// <value>
-  /// The local address to accept connections on. The default is <see 
cref="IPAddress.Any"/>, every
-  /// interface of the machine.
+  /// The local address to accept connections on. The default is <see 
cref="IPAddress.Loopback"/>,
+  /// the machine the application runs on.
   /// </value>
   /// <remarks>
   /// <para>
-  /// Set this to <see cref="IPAddress.Loopback"/> to accept connections only 
from the machine the
-  /// application runs on, which is what the diagnostic use this appender is 
meant for usually
-  /// needs.
+  /// The stream is unauthenticated and unencrypted, so reaching it from 
another machine is opt-in:
+  /// set this to <see cref="IPAddress.Any"/> or <see 
cref="IPAddress.IPv6Any"/> for that, and keep
+  /// untrusted parties away from the port.
   /// </para>
   /// </remarks>
   /// <exception cref="ArgumentNullException">The value specified is <see 
langword="null"/>.</exception>
@@ -183,7 +184,7 @@ public override void ActivateOptions()
     try
     {
       LogLog.Debug(_declaringType, $"Creating SocketHandler to listen on 
[{_listenAddress}]:[{_listeningPort}]");
-      _handler = new SocketHandler(_listenAddress, _listeningPort, 
_sendTimeoutMillis);
+      _handler = new(_listenAddress, _listeningPort, _sendTimeoutMillis);
     }
     catch (Exception ex)
     {
@@ -325,11 +326,12 @@ public SocketHandler(int port)
     /// block before that client is disconnected, or 0 to block 
indefinitely</param>
     /// <remarks>
     /// <para>
-    /// Creates a socket handler on the specified local server port.
+    /// Creates a socket handler on the specified local server port, listening 
on
+    /// <see cref="IPAddress.Loopback"/>.
     /// </para>
     /// </remarks>
     public SocketHandler(int port, int sendTimeoutMillis)
-      : this(IPAddress.Any, port, sendTimeoutMillis)
+      : this(IPAddress.Loopback, port, sendTimeoutMillis)
     { }
 
     /// <summary>
diff --git 
a/src/site/antora/modules/ROOT/pages/manual/configuration/appenders/telnetappender.adoc
 
b/src/site/antora/modules/ROOT/pages/manual/configuration/appenders/telnetappender.adoc
index 6751ca0c..adc29c1e 100644
--- 
a/src/site/antora/modules/ROOT/pages/manual/configuration/appenders/telnetappender.adoc
+++ 
b/src/site/antora/modules/ROOT/pages/manual/configuration/appenders/telnetappender.adoc
@@ -51,10 +51,12 @@ The default is `23`, the telnet port.
 
 `listenAddress`::
 The local address to accept connections on.
-The default is `0.0.0.0`, every interface of the machine.
+The default is `127.0.0.1`, the machine the application runs on, which is what 
diagnostic use
+usually needs.
 +
-Set it to `127.0.0.1` to accept connections only from the machine the 
application runs on, which is
-what diagnostic use usually needs.
+The stream is unauthenticated and unencrypted, so watching it from another 
machine is opt-in: set
+this to `0.0.0.0` for every IPv4 interface, or `::` for every IPv6 one, and 
keep untrusted parties
+away from the port.
 An IPv6 address may be given instead, and the listening socket follows its 
family.
 
 `sendTimeoutMillis`::
@@ -82,17 +84,17 @@ The appender therefore performs no authentication of its 
own.
 
 [WARNING]
 ====
-The connection is *unauthenticated* and *unencrypted*, and by default the 
appender listens on *all
-network interfaces*.
+The connection is *unauthenticated* and *unencrypted*.
 There is no option to require a credential or to enable TLS.
 
 Any client that can reach the port receives the full rendered log stream, 
including whatever the
 layout renders: user names, session identifiers, request parameters, stack 
traces.
-Keeping untrusted parties away from the port is the operator's responsibility, 
exactly as it is
-for a log file:
+The appender listens on `127.0.0.1` only, so that stays on the local machine 
until you widen
+`listenAddress`, and keeping untrusted parties away from the port is then the 
operator's
+responsibility, exactly as it is for a log file:
 
-* Set `listenAddress` to `127.0.0.1` unless clients on other machines really 
have to connect.
-* Only enable this appender on a trusted network.
+* Widen `listenAddress` only if clients on other machines really have to 
connect.
+* Only do so on a trusted network.
 * Restrict access to the port with a host firewall or network policy.
 * Prefer it for local or short-lived diagnostics rather than as a permanent 
logging destination.
 ====

Reply via email to