Skip to content

Commit

Permalink
modified foreign key relation chain between Session, Connection, Requ…
Browse files Browse the repository at this point in the history
…est, and Response
  • Loading branch information
tomcory committed Mar 2, 2024
1 parent 53833b1 commit ba0f85c
Show file tree
Hide file tree
Showing 9 changed files with 72 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ class HeimdallVpnService : VpnService() {
* @see [STOP_SERVICE]
*/
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
val existingSessionId = intent.getIntExtra("de.tomcory.heimdall.core.vpn.SESSION_ID", -1)

return when(intent.getIntExtra(VPN_ACTION, START_SERVICE)) {

START_SERVICE -> {
Expand All @@ -79,7 +81,7 @@ class HeimdallVpnService : VpnService() {
// launch the VPN components on a background thread
CoroutineScope(Dispatchers.IO).launch {
Timber.d("Launching service components...")
launchServiceComponents()
launchServiceComponents(existingSessionId)
Timber.d("VpnService started")
preferences.setVpnActive(true)
preferences.setVpnLastUpdated(System.currentTimeMillis())
Expand Down Expand Up @@ -136,7 +138,7 @@ class HeimdallVpnService : VpnService() {
* @return Whether the VPN interface was established successfully.
* @see [onStartCommand]
*/
private suspend fun launchServiceComponents() {
private suspend fun launchServiceComponents(existingSessionId: Int) {

// determine whether to launch in MitM mode
val doMitm = preferences.mitmEnable.first()
Expand Down Expand Up @@ -167,7 +169,8 @@ class HeimdallVpnService : VpnService() {
inboundStream = FileOutputStream(vpnInterface?.fileDescriptor),
databaseConnector = RoomDatabaseConnector(database),
vpnService = this,
doMitm = doMitm
doMitm = doMitm,
existingSessionId = existingSessionId
)
} catch (e: VpnComponentLaunchException) {
// shut down the VPN components if the ComponentManager could launch the components
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import de.tomcory.heimdall.core.database.HeimdallDatabase
import de.tomcory.heimdall.core.database.entity.Session
import de.tomcory.heimdall.core.proxy.HeimdallHttpProxyServer
import de.tomcory.heimdall.core.proxy.littleshoot.mitm.CertificateSniffingMitmManager
import de.tomcory.heimdall.core.util.InetAddressUtils
Expand All @@ -23,6 +24,7 @@ import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import timber.log.Timber
import java.io.File
Expand Down Expand Up @@ -194,11 +196,23 @@ class TrafficScannerViewModel @Inject constructor(
context,
database
)
proxyServer.start()

val sessionId = persistSession(System.currentTimeMillis())
proxyServer.start(sessionId)
proxyServer
}
}

private suspend fun persistSession(startTime: Long): Int {
val ids = try {
database.sessionDao().insert(Session(startTime = startTime))
} catch (e: Exception) {
Timber.e(e, "Error while persisting session")
emptyList()
}
return if (ids.isNotEmpty()) ids.first().toInt() else -1
}

private suspend fun stopProxyAndVpn(context: Context, proxyServer: HeimdallHttpProxyServer?) {
Timber.d("TrafficScannerViewModel.stopProxyAndVpn()")
_scanSetup.emit(true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,19 @@ import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.PrimaryKey

@Entity
@Entity(
foreignKeys = [
ForeignKey(
entity = Connection::class,
parentColumns = ["id"],
childColumns = ["connectionId"],
onDelete = ForeignKey.CASCADE
)
],
indices = [
androidx.room.Index(value = ["connectionId"])
]
)
data class Request(
@PrimaryKey(autoGenerate = true)
val id: Int = 0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import androidx.room.PrimaryKey
data class Response(
@PrimaryKey(autoGenerate = true)
val id: Int = 0,
val connectionId: Int,
val requestId: Int,
val timestamp: Long,
val headers: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,13 @@ public void removeWhiteListed(String hostAndPort) {
};
}

public void start() {
public void start(int sessionId) {
HttpProxyServerBootstrap serverBootstrap = DefaultHttpProxyServer
.bootstrap()
.withAddress(listeningAddress)
.withManInTheMiddle(getMitmManager())
.withTransparent(true)
.withFiltersSource(new HttpProxyFiltersSourceImpl(context, database));
.withFiltersSource(new HttpProxyFiltersSourceImpl(context, database, sessionId));

Timber.d("Proxy server prepared");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import android.os.Build
import android.system.OsConstants
import androidx.annotation.RequiresApi
import de.tomcory.heimdall.core.database.HeimdallDatabase
import de.tomcory.heimdall.core.database.entity.Connection
import de.tomcory.heimdall.core.database.entity.Request
import de.tomcory.heimdall.core.database.entity.Response
import de.tomcory.heimdall.core.proxy.littleshoot.HttpFiltersAdapter
Expand All @@ -23,22 +24,26 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import timber.log.Timber
import java.net.Inet6Address
import java.net.InetSocketAddress
import java.nio.charset.Charset
import java.util.Objects
import java.util.stream.Collectors
import kotlin.reflect.typeOf

class HttpProxyFiltersImpl(
originalRequest: HttpRequest?,
ctx: ChannelHandlerContext,
private val clientAddress: InetSocketAddress,
context: Context,
private val database: HeimdallDatabase
private val database: HeimdallDatabase,
private val sessionId: Int
) : HttpFiltersAdapter(originalRequest, ctx) {
private var isHttps = false
private var connectedRemoteAddress: InetSocketAddress? = null
private var aid = 0
private var packageName = ""
private var connectionId: Int = 0

private val isHttpsAttrKey = AttributeKey.valueOf<Boolean>("isHttps")
private val resolvedRemoteAddressKey = AttributeKey.valueOf<InetSocketAddress>("resolvedRemoteAddress")
Expand All @@ -59,6 +64,23 @@ class HttpProxyFiltersImpl(
aid = appFinder.getAppId(clientAddress.address, currentResolved.address, clientAddress.port, currentResolved.port, OsConstants.IPPROTO_TCP) ?: -1
packageName = appFinder.getAppPackage(aid) ?: ""


connectionId = database.connectionDao().insert(
Connection(
sessionId = sessionId,
protocol = "TCP",
ipVersion = if (currentResolved.address.hostAddress?.contains(':') == true) 6 else 4,
initialTimestamp = System.currentTimeMillis(),
initiatorId = aid,
initiatorPkg = packageName,
localPort = clientAddress.port,
remoteHost = currentResolved.hostString,
remoteIp = currentResolved.address.hostAddress ?: "",
remotePort = currentResolved.port,
isTracker = false
)
).let { if (it.isNotEmpty()) it.first().toInt() else 0 }

//wrap the access to the headers and content ByteBuf in try-catch blocks to prevent Netty weirdness
val headers = try {
fhr.headers().entries().stream()
Expand All @@ -77,7 +99,7 @@ class HttpProxyFiltersImpl(
}

val request = Request(
connectionId = 0,
connectionId = connectionId,
timestamp = System.currentTimeMillis(),
headers = headers,
content = content,
Expand Down Expand Up @@ -118,9 +140,8 @@ class HttpProxyFiltersImpl(
}

val response = Response(
connectionId = 0,
timestamp = System.currentTimeMillis(),
requestId = requestId,
timestamp = System.currentTimeMillis(),
headers = headers,
content = content,
contentLength = content.length,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,12 @@ public class HttpProxyFiltersSourceImpl extends HttpFiltersSourceAdapter {
private final Context context;
private final HeimdallDatabase database;

public HttpProxyFiltersSourceImpl(Context context, HeimdallDatabase database) {
private final int sessionId;

public HttpProxyFiltersSourceImpl(Context context, HeimdallDatabase database, int sessionId) {
this.context = context;
this.database = database;
this.sessionId = sessionId;
}

@Override
Expand All @@ -27,7 +30,7 @@ public HttpFilters filterRequest(HttpRequest originalRequest, ChannelHandlerCont
return new HttpProxyFiltersImpl(
originalRequest,
ctx,
(InetSocketAddress) ctx.channel().remoteAddress(), context, database);
(InetSocketAddress) ctx.channel().remoteAddress(), context, database, sessionId);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class ComponentManager(
private val inboundStream: FileOutputStream,
val databaseConnector: DatabaseConnector,
val vpnService: VpnService?,
existingSessionId: Int = -1,
val doMitm: Boolean = false,
val maxPacketSize: Int = 16413,
private val trackerTrie: Trie<String> = Trie {
Expand Down Expand Up @@ -95,7 +96,11 @@ class ComponentManager(
populateTrieFromRawFile(it.applicationContext, R.raw.adhosts, trackerTrie)
}

sessionId = runBlocking { return@runBlocking databaseConnector.persistSession(System.currentTimeMillis()) }
sessionId = if(existingSessionId < 0) {
runBlocking { return@runBlocking databaseConnector.persistSession(System.currentTimeMillis()) }
} else {
existingSessionId
}

/*
* Create and start the traffic handler threads. Since the threads rely on handlers to pass messages to each other
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,6 @@ class RoomDatabaseConnector(
val ids = try {
database.responseDao().insert(
Response(
connectionId = connectionId,
requestId = requestId,
timestamp = timestamp,
headers = if(headers.isNotEmpty()) headers.map { "${it.key}: ${it.value}" }.reduce { acc, s -> "$acc$s\n" } else "",
Expand Down

0 comments on commit ba0f85c

Please sign in to comment.