Record Class ClientHello

java.lang.Object
java.lang.Record
org.microproxy.ClientHello
Record Components:
sni - the host name the client asked for (Server Name Indication), or null when it sent none, or one that is not a valid host name
alpnProtocols - the application protocols the client offered (ALPN), in its order of preference, decoded as ISO-8859-1; empty without the extension
versions - the TLS versions the client offered, as wire values (0x0304 is TLS 1.3): those of the supported_versions extension, or else the message's legacy version
cipherSuites - the cipher suites the client offered, as wire values
extensionTypes - the types of the extensions the client sent, in order
raw - the handshake message: its type (1), 3-byte length and body, without the TLS record headers it arrived in

public record ClientHello(String sni, List<String> alpnProtocols, List<Integer> versions, List<Integer> cipherSuites, List<Integer> extensionTypes, byte[] raw) extends Record
A client's TLS ClientHello, the first message of a handshake, as the proxy read it before deciding whether to intercept a connection: after a CONNECT is accepted, and first thing on a connection to a transparent listener. The proxy reads it without consuming it: the same bytes then start the handshake the proxy completes itself, or are relayed to the server when the connection is tunnelled.

Filters see it in HttpFilters.proxyToServerAllowMitm(ClientHello), MITM managers in MitmManager.shouldIntercept(ClientHello, FlowContext), and anything holding the client connection's FlowContext through FlowContext.getClientHello().

Values are as the client sent them, GREASE values (RFC 8701) included, except for sni(), which is only set for a single, well-formed host name.

  • Field Details

  • Constructor Details

    • ClientHello

      public ClientHello(String sni, List<String> alpnProtocols, List<Integer> versions, List<Integer> cipherSuites, List<Integer> extensionTypes, byte[] raw)
      Creates a ClientHello, copying the lists and the message bytes.
      Parameters:
      sni - the requested host name, or null
      alpnProtocols - the offered application protocols
      versions - the offered TLS versions, as wire values
      cipherSuites - the offered cipher suites, as wire values
      extensionTypes - the types of the extensions sent
      raw - the handshake message, without record headers
      Throws:
      NullPointerException - if a list or raw is null
  • Method Details

    • raw

      public byte[] raw()
      Returns a copy of the handshake message bytes.
      Returns:
      a copy of the handshake message bytes
    • versionNames

      public List<String> versionNames()
      The offered TLS versions by name ("TLSv1.3", "TLSv1.2", ...), as the JDK names them, without GREASE and unknown values.
      Returns:
      the offered TLS versions by name, in the client's order
    • offersAlpn

      public boolean offersAlpn(String protocol)
      Whether the client offered protocol through ALPN.
      Parameters:
      protocol - an ALPN identifier, such as H2
      Returns:
      whether the client offered it
    • isGrease

      public static boolean isGrease(int value)
      Whether a value is a GREASE value (RFC 8701), which clients add to lists of cipher suites, extensions, versions and ALPN protocols to keep servers tolerant of unknown values.
      Parameters:
      value - a two-byte wire value
      Returns:
      whether value is one of the reserved 0x?A?A values
    • equals

      public boolean equals(Object o)
      Indicates whether some other object is "equal to" this one. The objects are equal if the other object is of the same class and if all the record components are equal. All components in this record class are compared with Objects::equals(Object,Object).
      Specified by:
      equals in class Record
      Parameters:
      o - the object with which to compare
      Returns:
      true if this object is the same as the o argument; false otherwise.
    • hashCode

      public int hashCode()
      Returns a hash code value for this object. The value is derived from the hash code of each of the record components.
      Specified by:
      hashCode in class Record
      Returns:
      a hash code value for this object
    • toString

      public String toString()
      Returns a string representation of this record class. The representation contains the name of the class, followed by the name and value of each of the record components.
      Specified by:
      toString in class Record
      Returns:
      a string representation of this object
    • httpAlpnProtocols

      public List<String> httpAlpnProtocols(boolean http2)
      The client's ALPN protocols that the proxy can speak over TLS: h2 (when withHttp2 is set), http/1.1 and http/1.0, in the client's order.
      Parameters:
      http2 - whether HTTP/2 may be included
      Returns:
      the HTTP protocols the client offered, possibly empty
    • sni

      public String sni()
      Returns the value of the sni record component.
      Returns:
      the value of the sni record component
    • alpnProtocols

      public List<String> alpnProtocols()
      Returns the value of the alpnProtocols record component.
      Returns:
      the value of the alpnProtocols record component
    • versions

      public List<Integer> versions()
      Returns the value of the versions record component.
      Returns:
      the value of the versions record component
    • cipherSuites

      public List<Integer> cipherSuites()
      Returns the value of the cipherSuites record component.
      Returns:
      the value of the cipherSuites record component
    • extensionTypes

      public List<Integer> extensionTypes()
      Returns the value of the extensionTypes record component.
      Returns:
      the value of the extensionTypes record component