1717import java .net .InetAddress ;
1818import java .net .InetSocketAddress ;
1919import java .net .SocketAddress ;
20+ import java .net .UnixDomainSocketAddress ;
2021import java .nio .ByteBuffer ;
2122import java .nio .charset .StandardCharsets ;
2223import java .util .Arrays ;
3132import org .eclipse .jetty .io .ClientConnectionFactory ;
3233import org .eclipse .jetty .io .Connection ;
3334import org .eclipse .jetty .io .EndPoint ;
35+ import org .eclipse .jetty .util .BufferUtil ;
3436import org .eclipse .jetty .util .Callback ;
3537import org .eclipse .jetty .util .Promise ;
3638import org .slf4j .Logger ;
@@ -207,23 +209,7 @@ protected ProxyProtocolConnection newProxyProtocolConnection(EndPoint endPoint,
207209 Executor executor = destination .getHttpClient ().getExecutor ();
208210 Tag tag = (Tag )destination .getOrigin ().getTag ();
209211 if (tag == null )
210- {
211- SocketAddress local = endPoint .getLocalSocketAddress ();
212- InetSocketAddress inetLocal = local instanceof InetSocketAddress ? (InetSocketAddress )local : null ;
213- InetAddress localAddress = inetLocal == null ? null : inetLocal .getAddress ();
214- SocketAddress remote = endPoint .getRemoteSocketAddress ();
215- InetSocketAddress inetRemote = remote instanceof InetSocketAddress ? (InetSocketAddress )remote : null ;
216- InetAddress remoteAddress = inetRemote == null ? null : inetRemote .getAddress ();
217- Tag .Family family = local == null || inetLocal == null ? Tag .Family .UNSPEC : localAddress instanceof Inet4Address ? Tag .Family .INET4 : Tag .Family .INET6 ;
218- tag = new Tag (Tag .Command .PROXY ,
219- family ,
220- Tag .Protocol .STREAM ,
221- localAddress == null ? null : localAddress .getHostAddress (),
222- inetLocal == null ? 0 : inetLocal .getPort (),
223- remoteAddress == null ? null : remoteAddress .getHostAddress (),
224- inetRemote == null ? 0 : inetRemote .getPort (),
225- null );
226- }
212+ tag = Tag .from (endPoint , true );
227213 return new ProxyProtocolConnectionV2 (endPoint , executor , getWrapped (), context , tag );
228214 }
229215
@@ -241,6 +227,72 @@ public static class Tag implements ClientConnectionFactory.Decorator
241227 */
242228 public static final Tag LOCAL = new Tag (Command .LOCAL , Family .UNSPEC , Protocol .UNSPEC , null , 0 , null , 0 , null );
243229
230+ /**
231+ * <p>Creates a {@code Tag} from the given {@link EndPoint}.</p>
232+ * <p>The {@code source} parameter indicates whether the {@code EndPoint}
233+ * is the local {@code EndPoint} (typical for clients), or the
234+ * remote {@code EndPoint} (typical for proxies).
235+ * In the latter case, the proxy wants to forward to the server the
236+ * information about the remote client so the {@code EndPoint} must
237+ * be that connected to the remote client (not to the server).</p>
238+ *
239+ * @param endPoint the {@code EndPoint} to create the {@code Tag} from
240+ * @param local whether the {@code EndPoint} is local or remote
241+ * @return a new {@code Tag} from the given {@code EndPoint}
242+ */
243+ public static Tag from (EndPoint endPoint , boolean local )
244+ {
245+ SocketAddress src = local ? endPoint .getLocalSocketAddress () : endPoint .getRemoteSocketAddress ();
246+ UnixDomainSocketAddress unixSrc = src instanceof UnixDomainSocketAddress ? (UnixDomainSocketAddress )src : null ;
247+ InetSocketAddress inetSrc = src instanceof InetSocketAddress ? (InetSocketAddress )src : null ;
248+ InetAddress srcAddress = inetSrc == null ? null : inetSrc .getAddress ();
249+ String srcAddr = unixSrc != null ? unixSrc .getPath ().toString ()
250+ : srcAddress != null ? srcAddress .getHostAddress () : null ;
251+
252+ int srcPort = inetSrc != null ? inetSrc .getPort () : 0 ;
253+
254+ Family family = Family .UNSPEC ;
255+ if (unixSrc != null )
256+ family = Family .UNIX ;
257+ else if (inetSrc != null )
258+ family = srcAddress instanceof Inet4Address ? V2 .Tag .Family .INET4 : V2 .Tag .Family .INET6 ;
259+
260+ Protocol protocol = src == null ? Protocol .UNSPEC : Protocol .STREAM ;
261+
262+ SocketAddress dst = local ? endPoint .getRemoteSocketAddress () : endPoint .getLocalSocketAddress ();
263+ UnixDomainSocketAddress unixDst = dst instanceof UnixDomainSocketAddress ? (UnixDomainSocketAddress )dst : null ;
264+ InetSocketAddress inetDst = dst instanceof InetSocketAddress ? (InetSocketAddress )dst : null ;
265+ InetAddress dstAddress = inetDst == null ? null : inetDst .getAddress ();
266+ String dstAddr = unixDst != null ? unixDst .getPath ().toString ()
267+ : dstAddress != null ? dstAddress .getHostAddress () : null ;
268+
269+ int dstPort = inetDst != null ? inetDst .getPort () : 0 ;
270+
271+ List <TLV > tlvs = null ;
272+ EndPoint .SslSessionData sslSessionData = endPoint .getSslSessionData ();
273+ int length ;
274+ if (sslSessionData != null )
275+ {
276+ length = 5 ;
277+ String cipherSuite = sslSessionData .cipherSuite ();
278+ byte [] cipherBytes = cipherSuite == null ? BufferUtil .EMPTY_BYTES : cipherSuite .getBytes (StandardCharsets .US_ASCII );
279+ length += 1 + 2 + cipherBytes .length ;
280+ byte [] value = new byte [length ];
281+ ByteBuffer byteBuffer = ByteBuffer .wrap (value );
282+ byteBuffer .put ((byte )TLV .PP2_CLIENT_SSL );
283+ byteBuffer .putInt (1 ); // Verify.
284+ if (cipherSuite != null )
285+ {
286+ byteBuffer .put ((byte )TLV .PP2_SUBTYPE_SSL_CIPHER );
287+ byteBuffer .putShort ((short )cipherBytes .length );
288+ byteBuffer .put (cipherBytes );
289+ }
290+ tlvs = List .of (new TLV (TLV .PP2_TYPE_SSL , value ));
291+ }
292+
293+ return new Tag (Command .PROXY , family , protocol , srcAddr , srcPort , dstAddr , dstPort , tlvs );
294+ }
295+
244296 private final Command command ;
245297 private final Family family ;
246298 private final Protocol protocol ;
@@ -285,6 +337,7 @@ public Tag(String srcIP, int srcPort, List<TLV> tlvs)
285337
286338 /**
287339 * <p>Creates a Tag with the given metadata.</p>
340+ * <p>Missing metadata will be derived from the underlying EndPoint.</p>
288341 *
289342 * @param command the LOCAL or PROXY command
290343 * @param family the protocol family
@@ -394,6 +447,11 @@ public enum Protocol
394447
395448 public static class TLV
396449 {
450+ public static final int PP2_TYPE_SSL = 0x20 ;
451+ public static final int PP2_CLIENT_SSL = 0x01 ;
452+ public static final int PP2_SUBTYPE_SSL_VERSION = 0x21 ;
453+ public static final int PP2_SUBTYPE_SSL_CIPHER = 0x23 ;
454+
397455 private final int type ;
398456 private final byte [] value ;
399457
@@ -571,6 +629,7 @@ protected void writePROXYBytes(EndPoint endPoint, Callback callback)
571629 private static class ProxyProtocolConnectionV2 extends ProxyProtocolConnection
572630 {
573631 private static final byte [] MAGIC = {0x0D , 0x0A , 0x0D , 0x0A , 0x00 , 0x0D , 0x0A , 0x51 , 0x55 , 0x49 , 0x54 , 0x0A };
632+ private static final int UNIX_ADDRESS_MAX_LENGTH = 108 ;
574633
575634 private final V2 .Tag tag ;
576635
@@ -589,87 +648,116 @@ protected void writePROXYBytes(EndPoint endPoint, Callback callback)
589648 capacity += 1 ; // version and command
590649 capacity += 1 ; // family and protocol
591650 capacity += 2 ; // length
592- capacity += 216 ; // max address length
651+ capacity += 2 * UNIX_ADDRESS_MAX_LENGTH ; // max address length
593652 List <V2 .Tag .TLV > tlvs = tag .getTLVs ();
594653 int vectorsLength = tlvs == null ? 0 : tlvs .stream ()
595654 .mapToInt (tlv -> 1 + 2 + tlv .getValue ().length )
596655 .sum ();
597656 capacity += vectorsLength ;
598657 ByteBuffer buffer = ByteBuffer .allocateDirect (capacity );
658+
599659 buffer .put (MAGIC );
660+
600661 V2 .Tag .Command command = tag .getCommand ();
601662 int versionAndCommand = (2 << 4 ) | (command .ordinal () & 0x0F );
602663 buffer .put ((byte )versionAndCommand );
603- V2 . Tag . Family family = tag . getFamily ();
664+
604665 String srcAddr = tag .getSourceAddress ();
605666 SocketAddress local = endPoint .getLocalSocketAddress ();
667+ UnixDomainSocketAddress unixLocal = local instanceof UnixDomainSocketAddress ? (UnixDomainSocketAddress )local : null ;
606668 InetSocketAddress inetLocal = local instanceof InetSocketAddress ? (InetSocketAddress )local : null ;
607669 InetAddress localAddress = inetLocal == null ? null : inetLocal .getAddress ();
608- if (srcAddr == null && localAddress != null )
609- srcAddr = localAddress .getHostAddress ();
670+ if (srcAddr == null )
671+ {
672+ if (unixLocal != null )
673+ srcAddr = unixLocal .getPath ().toString ();
674+ else if (localAddress != null )
675+ srcAddr = localAddress .getHostAddress ();
676+ }
677+
610678 int srcPort = tag .getSourcePort ();
611679 if (srcPort <= 0 && inetLocal != null )
612680 srcPort = inetLocal .getPort ();
681+
682+ V2 .Tag .Family family = tag .getFamily ();
613683 if (family == null )
614- family = local == null || inetLocal == null ? V2 .Tag .Family .UNSPEC : localAddress instanceof Inet4Address ? V2 .Tag .Family .INET4 : V2 .Tag .Family .INET6 ;
684+ {
685+ if (unixLocal != null )
686+ family = V2 .Tag .Family .UNIX ;
687+ else if (inetLocal != null )
688+ family = localAddress instanceof Inet4Address ? V2 .Tag .Family .INET4 : V2 .Tag .Family .INET6 ;
689+ else
690+ family = V2 .Tag .Family .UNSPEC ;
691+ }
692+
615693 V2 .Tag .Protocol protocol = tag .getProtocol ();
616694 if (protocol == null )
617695 protocol = local == null ? V2 .Tag .Protocol .UNSPEC : V2 .Tag .Protocol .STREAM ;
696+
618697 int familyAndProtocol = (family .ordinal () << 4 ) | protocol .ordinal ();
619698 buffer .put ((byte )familyAndProtocol );
620- int length = 0 ;
621- switch (family )
699+
700+ int length = switch (family )
622701 {
623- case UNSPEC :
624- break ;
625- case INET4 :
626- length = 12 ;
627- break ;
628- case INET6 :
629- length = 36 ;
630- break ;
631- case UNIX :
632- length = 216 ;
633- break ;
634- default :
635- throw new IllegalStateException ();
636- }
702+ case UNSPEC -> 0 ;
703+ case INET4 -> 12 ;
704+ case INET6 -> 36 ;
705+ case UNIX -> 2 * UNIX_ADDRESS_MAX_LENGTH ;
706+ };
637707 length += vectorsLength ;
638708 buffer .putShort ((short )length );
709+
639710 String dstAddr = tag .getDestinationAddress ();
640711 SocketAddress remote = endPoint .getRemoteSocketAddress ();
712+ UnixDomainSocketAddress unixRemote = remote instanceof UnixDomainSocketAddress ? (UnixDomainSocketAddress )remote : null ;
641713 InetSocketAddress inetRemote = remote instanceof InetSocketAddress ? (InetSocketAddress )remote : null ;
642714 InetAddress remoteAddress = inetRemote == null ? null : inetRemote .getAddress ();
643- if (dstAddr == null && remoteAddress != null )
644- dstAddr = remoteAddress .getHostAddress ();
715+ if (dstAddr == null )
716+ {
717+ if (unixRemote != null )
718+ dstAddr = unixRemote .getPath ().toString ();
719+ else if (remoteAddress != null )
720+ dstAddr = remoteAddress .getHostAddress ();
721+ }
722+
645723 int dstPort = tag .getDestinationPort ();
646724 if (dstPort <= 0 && inetRemote != null )
647725 dstPort = inetRemote .getPort ();
726+
648727 switch (family )
649728 {
650- case UNSPEC :
651- break ;
652- case INET4 :
653- case INET6 :
729+ case UNSPEC ->
730+ {
731+ // Nothing to do.
732+ }
733+ case INET4 , INET6 ->
734+ {
654735 buffer .put (InetAddress .getByName (srcAddr ).getAddress ());
655736 buffer .put (InetAddress .getByName (dstAddr ).getAddress ());
656737 buffer .putShort ((short )srcPort );
657738 buffer .putShort ((short )dstPort );
658- break ;
659- case UNIX :
739+ }
740+ case UNIX ->
741+ {
660742 int position = buffer .position ();
661743 if (srcAddr != null )
662- buffer .put (srcAddr .getBytes (StandardCharsets .US_ASCII ));
663- position = position + 108 ;
744+ {
745+ byte [] bytes = srcAddr .getBytes (StandardCharsets .US_ASCII );
746+ buffer .put (bytes , 0 , Math .min (bytes .length , UNIX_ADDRESS_MAX_LENGTH ));
747+ }
748+ position = position + UNIX_ADDRESS_MAX_LENGTH ;
664749 buffer .position (position );
665750 if (dstAddr != null )
666- buffer .put (dstAddr .getBytes (StandardCharsets .US_ASCII ));
667- position = position + 108 ;
751+ {
752+ byte [] bytes = dstAddr .getBytes (StandardCharsets .US_ASCII );
753+ buffer .put (bytes , 0 , Math .min (bytes .length , UNIX_ADDRESS_MAX_LENGTH ));
754+ }
755+ position = position + UNIX_ADDRESS_MAX_LENGTH ;
668756 buffer .position (position );
669- break ;
670- default :
671- throw new IllegalStateException ();
757+ }
758+ default -> throw new IllegalStateException ();
672759 }
760+
673761 if (tlvs != null )
674762 {
675763 for (V2 .Tag .TLV tlv : tlvs )
@@ -680,6 +768,7 @@ protected void writePROXYBytes(EndPoint endPoint, Callback callback)
680768 buffer .put (data );
681769 }
682770 }
771+
683772 buffer .flip ();
684773 endPoint .write (callback , buffer );
685774 }
0 commit comments