/* Ċ Ġ* ĠCopyright Ġ( c ) Ġ 2 0 2 0 ĠD uck Duck Go Ċ Ġ* Ċ Ġ* ĠLicensed Ġunder Ġthe ĠApache ĠLicense , ĠVersion Ġ 2 . 0 Ġ( the Ġ" License "); Ċ Ġ* Ġyou Ġmay Ġnot Ġuse Ġthis Ġfile Ġexcept Ġin Ġcompliance Ġwith Ġthe ĠLicense . Ċ Ġ* ĠYou Ġmay Ġobtain Ġa Ġcopy Ġof Ġthe ĠLicense Ġat Ċ Ġ* Ċ Ġ* ĠĠĠĠ Ġhttp :// www . apache . org / licenses / LICENSE - 2 . 0 Ċ Ġ* Ċ Ġ* ĠUnless Ġrequired Ġby Ġapplicable Ġlaw Ġor Ġagreed Ġto Ġin Ġwriting , Ġsoftware Ċ Ġ* Ġdistributed Ġunder Ġthe ĠLicense Ġis Ġdistributed Ġon Ġan Ġ" AS ĠIS " ĠBASIS , Ċ Ġ* ĠWITHOUT ĠWARRANTIES ĠOR ĠCONDITIONS ĠOF ĠANY ĠKIND , Ġeither Ġexpress Ġor Ġimplied . Ċ Ġ* ĠSee Ġthe ĠLicense Ġfor Ġthe Ġspecific Ġlanguage Ġgoverning Ġpermissions Ġand Ċ Ġ* Ġlimitations Ġunder Ġthe ĠLicense . Ċ Ġ*/ Ċ Ċ package Ġcom . duck duck go . mobile . android . vpn . processor . tcp . hostname Ċ Ċ import Ġtim ber . log . Tim ber Ċ import Ġkotlin . text . Charsets . US _ ASCII Ċ Ċ interface ĠEn crypted Request Host Extractor Ġ{ ĊĠĠĠ Ġfun Ġextract ( packet : ĠByteArray ): ĠString ? Ċ } Ċ Ċ // Ġbased Ġon Ġhttps :// www . ietf . org / rfc / rfc 5 2 4 6 . txt Ċ class ĠServer Name Indication Header Host Extractor ( private Ġval Ġtls Message Detector : ĠT ls Message Detector ) Ġ: ĠEn crypted Request Host Extractor Ġ{ ĊĊĠĠĠ Ġoverride Ġfun Ġextract ( packet : ĠByteArray ): ĠString ? Ġ{ ĊĊĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! is Client Hello Protocol ( packet )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . v (" Not Ġa ĠClient ĠHello Ġpacket ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġextract Host From Client Hello S ni Header ( packet ) ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( t : ĠThrowable ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . w ( t , Ġ" Failed Ġto Ġextract ĠClient Hello Ġdomain ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġnull ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġextract Host From Client Hello S ni Header ( packet : ĠByteArray ): ĠString ? Ġ{ ĊĠĠĠĠĠĠĠ Ġ// Ġthis Ġskip s Ġthe ĠTLS Ġheader , Ġtime Ġand ĠClient ĠRandom Ġ- Ġand Ġstarts Ġwith Ġthe Ġsession ĠID Ġlength ĊĠĠĠĠĠĠĠ Ġvar Ġindex Ġ= ĠSESSION _ ID _ INDEX ĊĊĠĠĠĠĠĠĠ Ġval ĠsessionId Length Ġ= Ġpacket [ index ]. toInt () Ġand Ġ 0 xFF ĊĠĠĠĠĠĠĠ Ġindex ++ ĊĠĠĠĠĠĠĠ Ġindex Ġ+= ĠsessionId Length ĊĊĠĠĠĠĠĠĠ Ġval Ġcipher Su ites Length Ġ= ĠHigh er Order Byte ( packet [ index ]) Ġ+ ĠLower Order Byte ( packet [ index Ġ+ Ġ 1 ]) ĊĠĠĠĠĠĠĠ Ġindex Ġ+= Ġ 2 ĊĠĠĠĠĠĠĠ Ġindex Ġ+= Ġcipher Su ites Length ĊĊĠĠĠĠĠĠĠ Ġval Ġcompression Method Length Ġ= Ġpacket [ index ]. toInt () ĊĠĠĠĠĠĠĠ Ġindex ++ ĊĠĠĠĠĠĠĠ Ġindex Ġ+= Ġcompression Method Length ĊĊĠĠĠĠĠĠĠ Ġval Ġextensions Length Ġ= ĠHigh er Order Byte ( packet [ index ]) Ġ+ ĠLower Order Byte ( packet [ index Ġ+ Ġ 1 ]) ĊĠĠĠĠĠĠĠ Ġindex Ġ+= Ġ 2 ĊĠĠĠĠĠĠĠ Ġif Ġ( extensions Length Ġ== Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġnull ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġs ni Header Start Ġ= Ġfind ServerName Indication Header Start ( packet , Ġindex , Ġextensions Length ) ĊĠĠĠĠĠĠĠ Ġif Ġ( sn i Header Start Ġ== Ġ- 1 ) Ġreturn Ġnull ĊĊĠĠĠĠĠĠĠ Ġindex Ġ= Ġs ni Header Start ĊĊĠĠĠĠĠĠĠ Ġ// Ġskip Ġ 5 Ġbytes Ġfor Ġdata Ġsizes Ġwe Ġdon 't Ġneed Ġto Ġknow Ġabout ĊĠĠĠĠĠĠĠ Ġindex Ġ+= Ġ 5 ĊĊĠĠĠĠĠĠĠ Ġval Ġserver Name Length Ġ= ĠHigh er Order Byte ( packet [ index ]) Ġ+ ĠLower Order Byte ( packet [ index Ġ+ Ġ 1 ]) ĊĠĠĠĠĠĠĠ Ġindex Ġ+= Ġ 2 ĊĠĠĠĠĠĠĠ Ġval Ġserver Name Bytes Ġ= ĠByteArray ( server Name Length ) ĊĊĠĠĠĠĠĠĠ Ġpacket . copy Into ( server Name Bytes , Ġ 0 , Ġindex , Ġindex Ġ+ Ġserver Name Length ) ĊĠĠĠĠĠĠĠ Ġreturn ĠString ( server Name Bytes , ĠUS _ ASCII ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġfind ServerName Indication Header Start ( ĊĠĠĠĠĠĠĠ Ġpacket : ĠByteArray , ĊĠĠĠĠĠĠĠ Ġextension StartIndex : ĠInt , ĊĠĠĠĠĠĠĠ Ġextensions Length : ĠInt ĊĠĠĠ Ġ): ĠInt Ġ{ ĊĠĠĠĠĠĠĠ Ġvar Ġextension Bytes Se ar ched Ġ= Ġ 0 ĊĠĠĠĠĠĠĠ Ġvar Ġindex Ġ= Ġextension StartIndex ĊĊĠĠĠĠĠĠĠ Ġwhile Ġ( extension Bytes Se ar ched Ġ< Ġextensions Length Ġ&& Ġindex Ġ< Ġpacket . size ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġextension Type Ġ= Ġadd High er Lower Order Bytes ( High er Order Byte ( packet [ index ]), ĠLower Order Byte ( packet [ index Ġ+ Ġ 1 ])) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġindex Ġ+= Ġ 2 ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( extension Type Ġ== ĠSERVER _ NAME _ EXTENSION _ TYPE ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġindex ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġextension Length Ġ= ĠHigh er Order Byte ( packet [ index ]) Ġ+ ĠLower Order Byte ( packet [ index Ġ+ Ġ 1 ]) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġindex Ġ+= Ġ 2 ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġskip Ġto Ġnext Ġextension , Ġif Ġthere Ġis Ġa Ġnext Ġone ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġindex Ġ+= Ġextension Length ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġrecord Ġnumber Ġof Ġextension Ġbytes Ġsearched , Ġwhich Ġis Ġthe Ġcurrent Ġextension Ġlength Ġ+ Ġ 4 Ġ( 2 Ġbytes Ġfor Ġtype , Ġ 2 Ġbytes Ġfor Ġlength ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġextension Bytes Se ar ched Ġ+= Ġextension Length Ġ+ Ġ 4 ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġ- 1 ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġis Client Hello Protocol ( packet : ĠByteArray ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ(! tls Message Detector . is Tls Message ( packet )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġfalse ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval ĠcontentType Ġ= Ġpacket [ 0 ]. toInt () ĊĠĠĠĠĠĠĠ Ġval Ġtls Version Major Ġ= Ġpacket [ 1 ]. toInt () ĊĠĠĠĠĠĠĠ Ġval Ġtls Version Minor Ġ= Ġpacket [ 2 ]. toInt () ĊĊĠĠĠĠĠĠĠ ĠTim ber . v (" Got ĠTLS Ġversion , Ġmajor :% d , Ġminor :% d . ĠContent Ġtype =% d . ĠPacket Ġsize =% d ", Ġtls Version Major , Ġtls Version Minor , ĠcontentType , Ġpacket . size ) ĊĊĠĠĠĠĠĠĠ Ġif Ġ( packet . size Ġ< ĠTLS _ HEADER _ SIZE ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġfalse ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġif Ġ( tls Version Major Ġ< Ġ 0 x 0 3 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . v (" TLS Ġversion Ġwouldn 't Ġinclude Ġa ĠS NI Ġheader Ġso Ġno Ġpoint Ġin Ġlooking Ġfurther Ġfor Ġit ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġfalse ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġif Ġ( contentType Ġ!= ĠTLS _ HAND SHA KE _ PACKET _ TYPE ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . v (" Not Ġa Ġhandshake Ġpacket ; Ġnot Ġgoing Ġto Ġfind ĠS NI Ġheader Ġin Ġhere ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġfalse ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġhandshake Length Ġ= Ġdetermine Tls Handshake Length ( packet ) ĊĊĠĠĠĠĠĠĠ Ġif Ġ( packet . size Ġ< Ġhandshake Length Ġ+ ĠTLS _ HEADER _ SIZE ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . w (" TLS Ġpacket Ġsize Ġunexpected . ĠHand shake Ġsize Ġreported Ġ% d Ġis Ġgreater Ġthan Ġtotal Ġpacket Ġsize Ġ% d ", Ġhandshake Length , Ġpacket . size ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġhandshake MessageType Ġ= Ġpacket [ TLS _ HEADER _ SIZE ] ĊĠĠĠĠĠĠĠ Ġif Ġ( handshake MessageType Ġ== Ġ 1 . to Byte ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . v (" This Ġis Ġa ĠClient Hello Ġmessage ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġtrue ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġfalse ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġdetermine Tls Handshake Length ( packet : ĠByteArray ): ĠInt Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġlength Part 1 Ġ= ĠHigh er Order Byte ( packet [ 3 ]) ĊĠĠĠĠĠĠĠ Ġval Ġlength Part 2 Ġ= ĠLower Order Byte ( packet [ 4 ]) ĊĠĠĠĠĠĠĠ Ġreturn Ġadd High er Lower Order Bytes ( length Part 1 , Ġlength Part 2 ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ// Ġfirst Ġbyte Ġmust Ġbe Ġmultip lied Ġby Ġ 2 5 6 Ġ( or Ġshl Ġ 8 ), Ġthen Ġadded Ġto Ġsecond ĊĠĠĠ Ġprivate Ġfun Ġadd High er Lower Order Bytes ( ĊĠĠĠĠĠĠĠ Ġhigher Order Byte : ĠHigh er Order Byte , ĊĠĠĠĠĠĠĠ Ġlower Order Byte : ĠLower Order Byte ĊĠĠĠ Ġ): ĠInt Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġhigher Int Ġ= Ġhigher Order Byte . byte . toInt () Ġshl Ġ 8 Ġand Ġ 0 xFF 0 0 ĊĠĠĠĠĠĠĠ Ġval Ġlower Int Ġ= Ġlower Order Byte . byte . toInt () Ġand Ġ 0 x 0 0 FF ĊĠĠĠĠĠĠĠ Ġreturn Ġhigher Int Ġ+ Ġlower Int ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠTLS _ HEADER _ SIZE Ġ= Ġ 5 ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠTLS _ HAND SHA KE _ PACKET _ TYPE Ġ= Ġ 2 2 ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠSESSION _ ID _ INDEX Ġ= Ġ 4 3 ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠSERVER _ NAME _ EXTENSION _ TYPE Ġ= Ġ 0 ĊĠĠĠ Ġ} Ċ } Ċ Ċ inline Ġclass ĠHigh er Order Byte ( val Ġbyte : ĠByte ) Ġ{ ĊĊĠĠĠ Ġoperator Ġfun Ġplus ( lower Order Byte : ĠLower Order Byte ): ĠInt Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġ( this . byte . toInt () Ġshl Ġ 8 Ġand Ġ 0 xFF 0 0 ) Ġ+ Ġ( lower Order Byte . byte . toInt () Ġand Ġ 0 x 0 0 FF ) ĊĠĠĠ Ġ} Ċ } Ċ Ċ inline Ġclass ĠLower Order Byte ( val Ġbyte : ĠByte ) Ċ