Hubbry Logo
Character Generator ProtocolCharacter Generator ProtocolMain
Open search
Character Generator Protocol
Community hub
Character Generator Protocol
logo
7 pages, 0 posts
0 subscribers
Be the first to start a discussion here.
Be the first to start a discussion here.
Character Generator Protocol
Character Generator Protocol
from Wikipedia
Character Generator Protocol
Communication protocol
AbbreviationCHARGEN
Purpose
  • Testing
  • Debugging
  • Measurement
Developer(s)Jon Postel
Introduction1983; 43 years ago (1983)
OSI layerApplication layer (7)
Port(s)tcp/19, udp/19
RFC(s)864

The Character Generator Protocol (CHARGEN) is a service of the Internet Protocol Suite defined in RFC 864 in 1983 by Jon Postel. It is intended for testing, debugging, and measurement purposes. The protocol is rarely used, as its design flaws allow for ready misuse.[1]

A host may connect to a server that supports the Character Generator Protocol on either Transmission Control Protocol (TCP) or User Datagram Protocol (UDP) port number 19. Upon opening a TCP connection, the server starts sending arbitrary characters to the connecting host and continues until the host closes the connection. In the UDP implementation of the protocol, the server sends a UDP datagram containing a random number (between 0 and 512) of characters every time it receives a datagram from the connecting host. Any data received by the server is discarded.

Inetd implementation

[edit]

On most Unix-like operating systems, a CHARGEN server is built into the inetd or xinetd daemon. The CHARGEN service is usually not enabled by default. It may be enabled by adding the following lines to the file /etc/inetd.conf and telling inetd to reload its configuration:

chargen   stream  tcp     nowait  root    internal
chargen   dgram   udp     wait    root    internal

Applications

[edit]

The CHARGEN service may be used as a source of a byte-stream for debugging TCP network code for proper bounds checking and buffer management. It may also be a source of generic payload for bandwidth measurement and/or QoS fine-tuning.[citation needed] Consideration must be given if hardware compression is active, as the output from the CHARGEN service is easily and efficiently compressed. This compression can cause bandwidth tests to report the size of the data after decompression, instead of the actual amount of data which passed the wire.

Sample session

[edit]

A typical CHARGEN service session looks like this: The user connects to the host using a telnet client. The user receives a stream of bytes. Although the specific format of the output is not prescribed by RFC 864, the recommended pattern (and a de facto standard) is shifted lines of 72 ASCII characters repeating.

$ telnet localhost chargen
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefg
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefgh
"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghi
#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghij
$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijk
%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijkl
&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklm
'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmn
()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmno
)*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnop
*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopq
+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqr
,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrs
-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrst
./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstu
/0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuv
0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvw
123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwx
23456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxy
3456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz
456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{
56789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|
6789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}
789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} 
89:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !
9:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"
:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"#
;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"#$
<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"#$%
=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"#$%&
>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"#$%&'
?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"#$%&'(
@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"#$%&'()
ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"#$%&'()*
BCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"#$%&'()*+
CDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"#$%&'()*+,
DEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"#$%&'()*+,-
EFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"#$%&'()*+,-.
FGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"#$%&'()*+,-./
GHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"#$%&'()*+,-./0
HIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"#$%&'()*+,-./01
IJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"#$%&'()*+,-./012
JKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"#$%&'()*+,-./0123
KLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"#$%&'()*+,-./01234
LMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"#$%&'()*+,-./012345
MNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"#$%&'()*+,-./0123456
NOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"#$%&'()*+,-./01234567
OPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"#$%&'()*+,-./012345678
PQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"#$%&'()*+,-./0123456789
QRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"#$%&'()*+,-./0123456789:
RSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"#$%&'()*+,-./0123456789:;
STUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"#$%&'()*+,-./0123456789:;<
TUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"#$%&'()*+,-./0123456789:;<=
UVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"#$%&'()*+,-./0123456789:;<=>
VWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"#$%&'()*+,-./0123456789:;<=>?
WXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"#$%&'()*+,-./0123456789:;<=>?@
XYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"#$%&'()*+,-./0123456789:;<=>?@A
YZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"#$%&'()*+,-./0123456789:;<=>?@AB
Z[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"#$%&'()*+,-./0123456789:;<=>?@ABC
[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"#$%&'()*+,-./0123456789:;<=>?@ABCD
\]^_`abcdefghijklmnopqrstuvwxyz{|} !"#$%&'()*+,-./0123456789:;<=>?@ABCDE
]^_`abcdefghijklmnopqrstuvwxyz{|} !"#$%&'()*+,-./0123456789:;<=>?@ABCDEF
^_`abcdefghijklmnopqrstuvwxyz{|} !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFG
_`abcdefghijklmnopqrstuvwxyz{|} !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGH
`abcdefghijklmnopqrstuvwxyz{|} !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHI
abcdefghijklmnopqrstuvwxyz{|} !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJ
bcdefghijklmnopqrstuvwxyz{|} !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJK
cdefghijklmnopqrstuvwxyz{|} !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKL
defghijklmnopqrstuvwxyz{|} !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLM
efghijklmnopqrstuvwxyz{|} !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMN
fghijklmnopqrstuvwxyz{|} !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNO
ghijklmnopqrstuvwxyz{|} !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOP
hijklmnopqrstuvwxyz{|} !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQ
ijklmnopqrstuvwxyz{|} !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQR
jklmnopqrstuvwxyz{|} !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRS
klmnopqrstuvwxyz{|} !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRST
lmnopqrstuvwxyz{|} !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTU
mnopqrstuvwxyz{|} !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUV
nopqrstuvwxyz{|} !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVW
opqrstuvwxyz{|} !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX
pqrstuvwxyz{|} !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXY
qrstuvwxyz{|} !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ
rstuvwxyz{|} !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[
stuvwxyz{|} !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\
tuvwxyz{|} !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]
uvwxyz{|} !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^
vwxyz{|} !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_
wxyz{|} !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`
xyz{|} !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`a
yz{|} !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ab
z{|} !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abc
{|} !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcd
|} !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcde
} !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdef
 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefg
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefgh
"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghi

^]
telnet> quit
Connection closed.

This continues until the TCP connection is closed as shown in the trace by ending the telnet session.

Visual output simulation

[edit]

For security reasons, most modern machines should have CHARGEN services disabled. The following is a Linux bash script that will simulate the visual appearance of the CHARGEN service in the terminal window. The script can be stopped by pressing Ctrl+C.

strg=""; for n in {32..126}; do  c=`printf '%x' $n | xxd -r -p`; strg=${strg}${c}; done; strg=${strg}${strg}; n=0; while :; do m=n%95; echo "${strg:m:72}"; n=$((n+1)); sleep .1; done;

Abuse

[edit]

The service was used maliciously to crash Microsoft domain name servers (DNS) running Windows NT 4.0 by piping the arbitrary characters straight into the DNS server listening port (telnet ntbox 19 | telnet ntbox 53).[2][3] However, the attack may have been a symptom of improper buffer management on the part of Microsoft's DNS service and not directly related to the CHARGEN service.[citation needed]

UDP CHARGEN is commonly used in denial-of-service attacks. By using a fake source address the attacker can send bounce traffic off a UDP CHARGEN application to the victim. UDP CHARGEN sends 200 to 1,000 times more data than it receives, depending upon the implementation. This "traffic multiplication" is also attractive to an attacker because it obscures the attacker's IP address from the victim.[citation needed]

CHARGEN was widely implemented on network-connected printers. As printer firmware was rarely updated on older models before CHARGEN and other security concerns were known, there may still be many network-connected printers which implement the protocol. Where these are visible to the Internet, they are invariably misused as denial of service vectors. Potential attackers often scan networks looking for UDP port 19 CHARGEN sources.

So notorious is the availability of CHARGEN in printers that some distributed denial of service trojans now use UDP port 19 for their attack traffic. The supposed aim is to throw investigators off the track; to have them looking for old printers rather than subverted computers.[citation needed]

See also

[edit]

References

[edit]
Revisions and contributorsEdit on WikipediaRead on Wikipedia
from Grokipedia
The Character Generator Protocol (CHARGEN) is a simple network service within the , defined in RFC 864 in 1983, designed as a and measurement tool that generates and transmits streams of data independently of any input received. It operates on port 19 using both TCP and UDP transports, with the TCP variant establishing a connection to deliver a continuous sequence of ASCII printable characters (typically in 72-character lines ending with and line feed) until the connection is closed, while the UDP variant responds to each incoming with a random-length reply of 0 to 512 characters from the same character set, maintaining no state between transactions. Originally intended for network testing—such as evaluating throughput, latency, or connection stability without complex interactions—CHARGEN has largely become obsolete in modern networks due to its lack of or access controls, rendering it unsuitable for production environments. Despite its intended use solely as a tool and recommendations against enabling it on publicly accessible servers, residual implementations persist, primarily contributing to vulnerabilities rather than legitimate use cases. A key notable aspect of CHARGEN is its exploitation in distributed reflective denial-of-service () attacks, particularly via UDP amplification, where attackers spoof victim IP addresses in small requests to open CHARGEN servers, eliciting disproportionately large responses (with a bandwidth amplification factor up to 358.8) that the target with traffic. To mitigate such risks, cybersecurity authorities recommend disabling CHARGEN services on internet-facing systems, implementing ingress filtering to block spoofed packets (per IETF BCP 38), and applying stateful inspection on firewalls to limit UDP responses.

Introduction

Definition and Purpose

The Character Generator Protocol (CHARGEN) is a simple network service defined within the that responds to client requests by generating a stream of ASCII characters, without regard to any input received from the client. Over TCP, it provides a continuous stream until the connection closes; over UDP, it sends a single response of 0 to 512 random-length characters. This protocol operates by transmitting unidirectionally from the server to the client, ignoring the contents or presence of incoming packets. The primary purpose of CHARGEN is to function as a and measurement tool, enabling verification of network connectivity, throughput capacity, and error rates through straightforward, non-interactive exchange that avoids complex protocol negotiations. By delivering predictable patterns of , it allows network administrators to assess transmission reliability and performance in early Internet environments without requiring stateful interactions. Key characteristics of CHARGEN include its stateless design, which maintains no history or session information, ensuring each request triggers independent data generation. The protocol produces output using the 95 printable ASCII characters (codes 32 through 126), arranged in an ordered sequence numbered 0 through 94 and cycling via modulo 95, formatted as 72-character lines ending with and line feed before repeating the cycle. Originally designed by Jon Postel in May 1983, CHARGEN aimed to provide a minimal and reliable service for troubleshooting connectivity issues in the nascent ARPA Internet, contributing to the suite of basic diagnostic protocols that supported early network development.

History and Development

The Character Generator Protocol (CHARGEN) was developed in 1983 by Jon Postel at the University of Southern California's Information Sciences Institute (USC/ISI) as one of several early utilities within the emerging TCP/IP protocol suite. Postel, a key figure in Internet protocol design during the ARPANET era, authored the protocol to provide a straightforward mechanism for network testing, reflecting the need for basic diagnostic tools in an environment constrained by limited computational hardware and nascent connectivity. This development occurred amid the transition from ARPANET to the broader ARPA Internet, where simple, resource-light services were essential for verifying host reachability and measuring basic performance metrics. Standardization followed shortly with the publication of RFC 864 on May 1, 1983, which outlined CHARGEN as a standard for the , with hosts expected to implement it if providing the service. The document specified implementations over both TCP and UDP on port 19. Although classified as an (STD 22) at the time, its experimental orientation aligned with the nature of early protocol evolution, prioritizing utility over rigorous validation. Following its initial release, RFC 864 received no substantive updates or revisions, remaining unchanged since 1983 and contributing to the protocol's gradual obsolescence in contemporary secure networks. Modern Internet systems are advised against implementing CHARGEN due to its potential for misuse and incompatibility with current security practices, rendering it largely deprecated. Nevertheless, the protocol persists in certain legacy systems, where it continues to serve as a rudimentary diagnostic in isolated or historical environments.

Protocol Specifications

RFC 864 Details

RFC 864, titled "Character Generator Protocol," is a concise document authored by and published in May 1983. Spanning just three pages, it outlines a simple network service designed as a tool for debugging and measurement, explicitly stating that the character generator "simply sends data without regard to the input." The RFC lacks formal sections on abstract or references, instead dividing its content into five main parts: an introduction, descriptions of the TCP-based and UDP-based services, data syntax specifications, and a brief example. The document specifies port 19 as the default for both TCP and UDP implementations of the protocol. In TCP mode, the service establishes a connection and delivers a continuous stream of data until the connection closes, with the server generating responses independently of any client input. For UDP, it operates on a basis, where the server responds to each incoming datagram with a separate datagram containing a random number of characters between 0 and 512. Central to the protocol are the character generation rules detailed in the data syntax section. The server produces lines of exactly 72 characters, each comprising the 95 printable ASCII characters (decimal codes 32 to 126), sorted in ascending order and numbered from to 94, terminated by a and line feed. These lines follow a fixed cyclic : the Nth line uses characters offset by N 95, starting from position 0 to 71 in the sequence, creating a shifting that wraps around without repetition until the cycle completes. This deterministic output aids in verifying and reliability, as emphasized in the introduction's purpose for operational testing. RFC 864 is designated as a standard for the Internet community ( STD 22), intended as an informational service for network diagnostics. An example in the document illustrates a sample TCP interaction, showing the server initiating data transmission immediately upon connection with the first cyclic line.

Transmission Modes

The Character Generator Protocol (CHARGEN) supports two primary transmission modes: TCP and UDP, both utilizing the default port 19, with no built-in or session management mechanisms. In TCP mode, CHARGEN operates as a connection-oriented service, where the server establishes a reliable, ordered connection with the client upon receiving a connection request on port 19. Once connected, the server immediately begins transmitting a continuous of without regard to any input from the client, continuing until the client terminates the connection either abruptly or through a careful close. This consists of recommended 72-character lines comprising ASCII printing characters (decimal codes 32 through 126), sorted in ascending order, followed by a and line feed; the server discards any received and relies on TCP's flow control to manage transmission rates. This mode is particularly suited for testing sustained throughput and connection stability due to its ordered and reliable delivery guarantees. In contrast, UDP mode functions as a connectionless, , where the server responds independently to each incoming received on port 19 by sending a single reply containing 0 to 512 random ASCII characters, again ignoring the content of the request. Each response is generated anew without retaining any state or history from prior interactions, making it ideal for quick, one-off probes but susceptible to or reordering inherent to UDP. The lack of persistent connections in this mode emphasizes its utility for lightweight, high-volume diagnostic testing rather than prolonged data exchanges. The operational differences between these modes highlight CHARGEN's flexibility for various network measurement scenarios: TCP ensures complete and ordered data delivery for in-depth reliability assessments, while UDP enables rapid, fire-and-forget transmissions that simulate bursty or unreliable conditions, though both modes share the protocol's core simplicity of generating characters without input processing.

Implementation

System Integration

In operating systems, the Character Generator Protocol (CHARGEN) is typically integrated through super-servers such as or its extended version, xinetd, which manage lightweight network services on demand. These super-servers listen for incoming connections and invoke the appropriate handler based on configuration entries in files like /etc/.conf or /etc/xinetd.d/chargen. For CHARGEN, the configuration specifies port 19 for both TCP and UDP protocols, with the service often marked as "internal" to indicate that the super-server handles the protocol logic directly without requiring a separate ; example entries include "chargen stream tcp nowait root internal" for TCP and "chargen dgram udp wait root internal" for UDP. CHARGEN has been available by default in many BSD-derived systems, such as and older versions of Solaris, where it was often enabled in legacy configurations for network testing purposes. In these environments, the service is bundled with the base system and activated via the super-server setup without additional installation. Similarly, older distributions, including those using or early xinetd implementations, included CHARGEN entries in their default configuration files, though typically commented out to prevent unintended exposure. (Note: This doc references legacy Solaris services; for specifics, see historical SMF manifests in Solaris 10 documentation archives.) (Adapted for stable LFS context on xinetd internals.) Upon startup, the super-server binds to port 19 and monitors for connections using the specified protocols. When a request arrives, it spawns a or handles the connection internally for stateless services like CHARGEN, generating the character without maintaining persistent state between sessions; this on-demand model minimizes resource usage compared to standalone daemons. The configuration supports both TCP mode, where data flows continuously until the connection closes, and UDP mode for discrete packet responses. In modern distributions, CHARGEN is rarely included or enabled by default due to associated security risks, such as potential amplification in denial-of-service attacks, leading most systems to exclude it from standard packages. Administrators seeking to implement it must manually compile or install from open-source implementations inspired by RFC 864, then configure the super-server accordingly, often requiring explicit enabling of the service files. (CIS benchmark for , applicable to general practices.)

Programming Examples

Implementing a CHARGEN server requires binding to port 19 and generating data according to the specifications in RFC 864, which defines the protocol for both TCP and UDP transports. The server ignores any incoming data and continuously produces a stream of ASCII printable characters (codes 32 through 126) in a cyclic pattern resembling a "barber pole" effect.

Basic TCP Server Pseudocode

A basic TCP CHARGEN server listens on port 19, accepts connections, and sends lines of 72 characters each, followed by a carriage return and line feed (CR LF), cycling through the 95 printable ASCII characters with an offset per line until the client disconnects. The following pseudocode illustrates this process:

initialize socket with TCP, bind to port 19 listen for connections while true: accept client connection line_offset = 0 while client connected: for column = 0 to 71: char_index = (line_offset + column) mod 95 char = printable_ascii[char_index] // ASCII 32-126, indexed 0-94 send char to client send CR LF to client line_offset += 1 close client connection close socket

initialize socket with TCP, bind to port 19 listen for connections while true: accept client connection line_offset = 0 while client connected: for column = 0 to 71: char_index = (line_offset + column) mod 95 char = printable_ascii[char_index] // ASCII 32-126, indexed 0-94 send char to client send CR LF to client line_offset += 1 close client connection close socket

This loop ensures a continuous stream without regard to client input, as required by the protocol.

UDP Server Example in Python

For UDP, the server responds to each incoming with a single containing up to 512 bytes of data in the same character pattern, but without maintaining state across requests; a typical implementation generates approximately 511 bytes per response to maximize utility for testing. The Python standard library's socket module provides a straightforward way to implement this. The example below uses IPv4, binds to port 19, and generates lines until reaching the byte limit:

python

import socket # Printable ASCII characters (32-126), 95 chars CHARS = [chr(i) for i in range(32, 127)] NEWLINE = '\r\n' PORT = 19 WIDTH = 72 MAX_BYTES = 512 def generate_response(): response = '' line_num = 0 while len(response.encode('ascii')) < MAX_BYTES: line = ''.join(CHARS[(line_num + col) % 95] for col in range(WIDTH)) response += line + NEWLINE line_num += 1 return response.encode('ascii')[:MAX_BYTES - 1] # Ensure under 512 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.bind(('', PORT)) while True: data, addr = sock.recvfrom(1024) # Ignore data, just get addr response = generate_response() sock.sendto(response, addr)

import socket # Printable ASCII characters (32-126), 95 chars CHARS = [chr(i) for i in range(32, 127)] NEWLINE = '\r\n' PORT = 19 WIDTH = 72 MAX_BYTES = 512 def generate_response(): response = '' line_num = 0 while len(response.encode('ascii')) < MAX_BYTES: line = ''.join(CHARS[(line_num + col) % 95] for col in range(WIDTH)) response += line + NEWLINE line_num += 1 return response.encode('ascii')[:MAX_BYTES - 1] # Ensure under 512 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.bind(('', PORT)) while True: data, addr = sock.recvfrom(1024) # Ignore data, just get addr response = generate_response() sock.sendto(response, addr)

This code produces independent responses for each datagram, aligning with the UDP mode where no stream continuity is maintained.

C Implementation Outline

In C, a CHARGEN server leverages the Berkeley sockets API from <sys/socket.h> to create and manage connections, often using fork() to handle multiple clients concurrently in a multi-process model. The outline below shows the core structure for a TCP server, including socket setup, acceptance loop, and character generation using write():

c

#include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <unistd.h> #include <stdio.h> #include <string.h> #define PORT 19 #define WIDTH 72 #define NUM_CHARS 95 // Printable ASCII 32-126 int main() { int sockfd, clientfd; struct sockaddr_in server_addr, client_addr; socklen_t client_len = sizeof(client_addr); char buffer[WIDTH + 2]; // +2 for CR LF int line_offset = 0; // Printable chars array (initialize with ASCII 32-126) char chars[NUM_CHARS]; for (int i = 0; i < NUM_CHARS; i++) { chars[i] = 32 + i; } sockfd = socket(AF_INET, SOCK_STREAM, 0); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(PORT); server_addr.sin_addr.s_addr = INADDR_ANY; bind(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)); listen(sockfd, 5); while (1) { clientfd = accept(sockfd, (struct sockaddr*)&client_addr, &client_len); if (fork() == 0) { // Child process close(sockfd); line_offset = 0; while (1) { for (int col = 0; col < WIDTH; col++) { int idx = (line_offset + col) % NUM_CHARS; buffer[col] = chars[idx]; } buffer[WIDTH] = '\r'; buffer[WIDTH + 1] = '\n'; write(clientfd, buffer, WIDTH + 2); line_offset++; } close(clientfd); exit(0); } close(clientfd); } close(sockfd); return 0; }

#include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <unistd.h> #include <stdio.h> #include <string.h> #define PORT 19 #define WIDTH 72 #define NUM_CHARS 95 // Printable ASCII 32-126 int main() { int sockfd, clientfd; struct sockaddr_in server_addr, client_addr; socklen_t client_len = sizeof(client_addr); char buffer[WIDTH + 2]; // +2 for CR LF int line_offset = 0; // Printable chars array (initialize with ASCII 32-126) char chars[NUM_CHARS]; for (int i = 0; i < NUM_CHARS; i++) { chars[i] = 32 + i; } sockfd = socket(AF_INET, SOCK_STREAM, 0); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(PORT); server_addr.sin_addr.s_addr = INADDR_ANY; bind(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)); listen(sockfd, 5); while (1) { clientfd = accept(sockfd, (struct sockaddr*)&client_addr, &client_len); if (fork() == 0) { // Child process close(sockfd); line_offset = 0; while (1) { for (int col = 0; col < WIDTH; col++) { int idx = (line_offset + col) % NUM_CHARS; buffer[col] = chars[idx]; } buffer[WIDTH] = '\r'; buffer[WIDTH + 1] = '\n'; write(clientfd, buffer, WIDTH + 2); line_offset++; } close(clientfd); exit(0); } close(clientfd); } close(sockfd); return 0; }

This implementation forks a new process per client to send the cyclic lines via write(), ensuring the server remains responsive; a similar structure applies to UDP by using SOCK_DGRAM and recvfrom()/sendto(). CHARGEN implementations per RFC 864 perform no input validation, as the protocol explicitly disregards received data. However, custom builds may incorporate timeouts on connections or datagram handling—such as using select() or alarm() in C, or socket.settimeout() in Python—to mitigate potential resource exhaustion from persistent clients, though this extends beyond the minimal RFC requirements. As an alternative to custom servers, inetd can invoke a simple handler script or binary for CHARGEN on supported systems.

Applications

Network Testing

The Character Generator Protocol (CHARGEN) serves as a foundational tool for verifying network performance and reliability by actively generating data streams that simulate real-world traffic conditions. Specified in RFC 864, it operates on port 19 using either TCP for continuous streams or UDP for discrete responses, allowing testers to evaluate key metrics without complex setups. In throughput measurement, clients establish connections to the CHARGEN service to produce sustained traffic volumes, enabling assessments of bandwidth constraints, packet loss, and latency across LAN and WAN infrastructures. For instance, the TCP mode delivers an unending sequence of characters at a steady rate, facilitating load simulation to identify bottlenecks in data transfer efficiency. Connectivity diagnostics leverage a basic telnet session to port 19, where a successful link-up and immediate receipt of generated characters confirm host reachability and service responsiveness, particularly valuable for validating firewall configurations. This straightforward probe helps isolate issues in path availability without additional diagnostics. For error detection, the protocol's output of patterned 72-character lines—such as sequential ASCII symbols—permits observers to spot disruptions like garbled sequences or gaps, signaling transmission errors or misconfigurations in foundational network environments. These observable patterns provide a low-overhead method to pinpoint integrity problems during testing. In early TCP/IP networks during the 1980s, CHARGEN found application in troubleshooting efforts to mimic traffic loads absent dedicated utilities.

Diagnostic Tools

CHARGEN, defined in RFC 864, serves as a basic tool for generating continuous streams of data or test patterns, enabling its integration with other network utilities to facilitate comprehensive diagnostics. Scripting integrations further enhance CHARGEN's diagnostic utility, particularly through tools like netcat (nc), which can automate sessions to capture and log output streams. For instance, netcat commands can initiate TCP or UDP connections to a CHARGEN server on port 19, redirecting responses to files for subsequent analysis of network behaviors such as jitter or packet reordering in automated test scripts. This method supports repeatable diagnostics by combining CHARGEN's predictable data generation with netcat's flexibility in handling connections and output processing. In legacy systems, CHARGEN formed part of standard network service suites in SunOS and early UNIX environments for basic network services. Similarly, early Cisco IOS implementations included CHARGEN among small servers for router interface testing, aiding in the evaluation of port functionality and basic traffic handling prior to more advanced configurations. However, CHARGEN's limitations in modern diagnostics stem from its fixed, non-configurable output, which lacks the precision for variable bandwidth, protocol-specific testing, or detailed metrics control. It has largely been superseded by tools like iperf, which offer greater flexibility in generating controlled traffic for accurate performance assessment.

Security Considerations

Inherent Vulnerabilities

The Character Generator Protocol (CHARGEN), as defined in RFC 864, operates in a stateless manner, maintaining no history or state information between interactions, particularly in its UDP implementation. This design lacks any mechanism for client verification or authentication, enabling any remote host to initiate requests and trigger the server to generate and transmit data without restriction. As a result, attackers can exploit this unauthenticated access to induce unlimited output from the server, potentially draining computational resources such as CPU and memory on vulnerable systems. The protocol's output is highly predictable, consisting of fixed sequences of ASCII printing characters arranged in 72-character lines that cycle through a sorted pattern of 95 printable characters, concluding each line with a carriage return and line feed. This deterministic generation process allows for easy spoofing of requests, as adversaries require no knowledge of internal server states or secrets to mimic legitimate traffic and elicit responses. In the UDP mode, responses are sent unicast to the source IP of the request, but the lack of source validation enables attackers to spoof the victim's IP, directing amplified responses toward the target. In TCP mode, CHARGEN provides a continuous stream of data upon connection establishment, transmitting characters indefinitely until the connection is terminated by either party, with no built-in rate limiting or throttling mechanisms specified in the protocol. This feature, intended for diagnostic purposes, can lead to sustained consumption of server CPU cycles for data generation and network bandwidth for transmission, particularly on systems lacking external safeguards. The protocol's reliance on underlying transport layer flow control, such as TCP's windowing, offers minimal protection against prolonged sessions, rendering it susceptible to resource exhaustion in environments where the service remains enabled.

Exploitation in Attacks

The Character Generator Protocol (CHARGEN) is frequently exploited in distributed denial-of-service (DDoS) amplification attacks, where adversaries spoof the victim's IP address in small UDP requests sent to publicly accessible CHARGEN servers. These servers, responding with large streams of character data—typically up to 512 bytes per response—direct the amplified traffic toward the target, creating a bandwidth multiplication effect. This results in amplification factors exceeding 350:1, allowing attackers to generate substantial volumetric floods with minimal outbound traffic from their controlled sources. CharGEN flood attacks have been documented in numerous incidents from 2014 onward, often leveraging botnet variants that target Internet of Things (IoT) devices with inadvertently enabled CHARGEN services for reflection. For instance, early exploits highlighted in 2014 involved widespread scanning for open CHARGEN reflectors, enabling volumetric assaults reaching up to 100 Gbps or more against enterprise networks. These attacks exploit the protocol's legacy design, turning misconfigured devices into unwitting amplifiers and contributing to sustained network disruptions in sectors like finance and e-commerce. In reflection techniques, CHARGEN is commonly integrated with other UDP-based protocols such as DNS and NTP to form multi-vector DDoS campaigns, overwhelming defenses through diverse traffic patterns. The preference for UDP mode stems from its stateless nature, which simplifies IP spoofing and evades basic source validation, allowing bots to impersonate the victim across multiple reflector pools without establishing connections. This combination enhances attack potency by distributing the reflective load and complicating mitigation efforts. In March 2024, researchers disclosed a new class of "Loop DoS" attacks targeting UDP application-layer protocols, including CHARGEN. These attacks exploit misconfigurations where two endpoints (e.g., a CHARGEN server and an ECHO server) continuously reflect and amplify traffic to each other, creating self-sustaining loops that can overwhelm networks with minimal attacker effort. Scans identified approximately 300,000 systems vulnerable to such loops involving CHARGEN, highlighting ongoing risks despite mitigation efforts. To counter Loop DoS, administrators should disable unnecessary UDP services, implement strict firewall rules to prevent inter-service communication, and monitor for anomalous traffic patterns. As of 2025, CHARGEN's role in standalone attacks has declined due to widespread adoption of ingress filtering and service disablement on exposed hosts, reducing the pool of available reflectors. However, it persists in hybrid attacks that blend amplification with direct floods, particularly targeting cloud infrastructure where rapid scaling can amplify service outages.

Practical Examples

Session Demonstration

A typical TCP session with the Character Generator Protocol (CHARGEN) begins when a client establishes a connection to port 19 on a server supporting the protocol. Upon connection, the server immediately starts transmitting a continuous stream of data without requiring any input from the client. This stream consists of lines, each containing 72 ASCII printable characters (from space at code 32 to tilde '~' at code 126), followed by a carriage return and line feed (CR LF). The characters cycle through a fixed sequence of 95 printable symbols in ascending ASCII order, with each subsequent line shifting the starting position by one character in the cycle. For example, the first line begins with a space followed by:

!"# $%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRS

!"# $%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRS

The second line shifts to start with '!':

!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRST

!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRST

This pattern continues indefinitely, limited only by TCP flow control, until the client disconnects the session. In contrast, a UDP session involves sending a single to the server's port 19, to which the server responds with one containing a random number of characters (between 0 and 512) chosen from the same set of 95 printable ASCII characters. Unlike TCP, there is no persistent connection or continuity between requests; each UDP elicits an independent response. Implementations often generate a contiguous segment from the cyclic sequence starting at a random offset, though the RFC does not specify the exact selection method. For instance, a request might yield a response beginning with characters such as:

!"# $%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNO

!"# $%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNO

illustrating a possible position in the cycle including the space. The response size varies to simulate network load without establishing state. To reproduce these sessions from the command line, users can employ tools like (nc). For TCP, the command nc <host> 19 initiates a connection and displays the streaming output in real time, which can be captured by redirecting to a file (e.g., nc <host> 19 > output.txt) for verification against the expected cyclic pattern. For UDP, a simple can be sent using echo "" | nc -u <host> 19, prompting a single response packet that can be observed via packet capture tools or logged output. The TCP session persists and generates data continuously until the client explicitly terminates the connection, such as by closing the socket or sending a control signal like Ctrl+C in an interactive terminal. UDP interactions, however, are inherently one-shot, completing with the immediate exchange of a single request-response pair per invocation.

Output Visualization

The Character Generator Protocol (CHARGEN), as defined in RFC 864, produces a continuous of printable ASCII characters ranging from (ASCII 32) to tilde (ASCII 126), for a total of 95 distinct symbols. The output begins with the first line consisting of the initial 72 characters in this sequence, followed by a and line feed (CR LF). Each subsequent line shifts the starting position by one character forward, wrapping around modulo 95, creating a repeating, cyclical pattern that ensures no line exactly repeats another within the 95-line cycle. This shifting mechanism results in a visually distinctive diagonal progression when viewed as a block of text, where each line appears to scroll leftward relative to the previous one, evoking the effect of a . To illustrate, the following excerpt shows the first five lines of a typical CHARGEN output stream (leading space on first line noted; characters represented as they appear in standard ASCII rendering):

!"# $%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRS !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRST "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTU #$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUV $%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVW

!"# $%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRS !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRST "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTU #$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUV $%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVW

The pattern continues indefinitely until the connection is terminated, with lines 95 onward repeating the cycle from the first line. This representation highlights the uniform, predictable nature of the stream, which was designed for diagnostic testing of and reliability but also facilitates straightforward due to its non-random . Notably, the protocol specifies no colors, fonts, or additional formatting; the output is purely a raw sequence of bytes representing these printable characters, terminated only by CR LF at the end of each 72-character line. For a more precise examination, especially to observe non-printable control sequences like CR LF or to inspect the raw byte stream beyond visual rendering, terminal emulators such as or , or hex viewers like xxd, are recommended tools. These allow users to connect via TCP or UDP on port 19 and capture the output in its native form, revealing the protocol's simplicity and adherence to basic ASCII standards.
Add your contribution
Related Hubs
User Avatar
No comments yet.