Skip to content

Commit

Permalink
allow matching parts of hosts
Browse files Browse the repository at this point in the history
  • Loading branch information
danthe1st committed Feb 29, 2024
1 parent 7b21ddf commit 76e9cb9
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 4 deletions.
11 changes: 11 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@
<artifactId>slf4j-simple</artifactId>
<version>${slf4j-version}</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.10.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
Expand All @@ -42,6 +48,11 @@
<release>21</release>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package io.github.danthe1st.httpsintercept.control;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class HostMatcher {
private Set<String> exactHosts = new HashSet<>();
private Set<String> hostParts = new HashSet<>();

public static HostMatcher load(Path config) throws IOException {
if(!Files.exists(config)){
Files.createFile(config);
return load(Collections.emptyList());
}
List<String> hostDeclarations = Files.readAllLines(config);
return load(hostDeclarations);
}

static HostMatcher load(List<String> hostDeclarations) {
Set<String> exactHosts = new HashSet<>();
Set<String> hostParts = new HashSet<>();
for(String ignored : hostDeclarations){
if(ignored.startsWith("*.")){
hostParts.add(ignored.substring(2));
}else{
exactHosts.add(ignored);
}
}
return new HostMatcher(exactHosts, hostParts);
}

HostMatcher(Set<String> exactHosts, Set<String> hostParts) {
this.exactHosts = Set.copyOf(exactHosts);
this.hostParts = Set.copyOf(hostParts);
}

public boolean matches(String hostname) {
return exactHosts.contains(hostname) || doesMatchPart(hostname);
}

private boolean doesMatchPart(String hostname) {
if(hostParts.isEmpty()){
return false;
}

int index = 0;
while((index = hostname.indexOf('.', index) + 1) != 0 && index < hostname.length()){
if(hostParts.contains(hostname.substring(index))){
return true;
}
}

return false;
}

Set<String> getExactHosts() {
return Collections.unmodifiableSet(exactHosts);
}

Set<String> getHostParts() {
return Collections.unmodifiableSet(hostParts);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;

import io.github.danthe1st.httpsintercept.control.HostMatcher;
import io.github.danthe1st.httpsintercept.handler.raw.RawForwardIncomingRequestHandler;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelHandler;
Expand All @@ -27,13 +28,13 @@ public class CustomSniHandler extends SniHandler {

private final Bootstrap clientBootstrapTemplate;

private final Set<String> ignoredHosts;
private final HostMatcher ignoredHosts;

public CustomSniHandler(Mapping<? super String, ? extends SslContext> mapping, Bootstrap clientBootstrapTemplate) throws IOException {
super(mapping);
this.clientBootstrapTemplate = clientBootstrapTemplate;

ignoredHosts = loadIgnoredHosts();
ignoredHosts = HostMatcher.load(Path.of("ignoredHosts.txt"));
}

private static Set<String> loadIgnoredHosts() throws IOException {
Expand All @@ -50,8 +51,8 @@ private static Set<String> loadIgnoredHosts() throws IOException {
@Override
protected void replaceHandler(ChannelHandlerContext channelHandlerContext, String hostname, SslContext sslContext) throws Exception {
ChannelPipeline pipeline = channelHandlerContext.pipeline();
if(ignoredHosts.contains(hostname)){
LOG.debug("skipping hostname {}", hostname);
if(ignoredHosts.matches(hostname)){
LOG.info("skipping hostname {}", hostname);

boolean foundThis = false;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package io.github.danthe1st.httpsintercept.control;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.Collections;
import java.util.List;
import java.util.Set;

import org.junit.jupiter.api.Test;

class HostMatcherTests {
@Test
void testExactMatch() {
HostMatcher matcher = new HostMatcher(Set.of("example.com"), Collections.emptySet());
assertTrue(matcher.matches("example.com"));
assertFalse(matcher.matches("github.com"));
}

@Test
void testPartMatch() {
HostMatcher matcher = new HostMatcher(Collections.emptySet(), Set.of("example.com"));
assertTrue(matcher.matches("host.example.com"));
assertTrue(matcher.matches(".example.com"));
assertFalse(matcher.matches("host.github.com"));
assertFalse(matcher.matches("example.com"));
assertFalse(matcher.matches("example.com."));
assertFalse(matcher.matches(""));
assertFalse(matcher.matches("."));
}

@Test
void testLoadExact() {
HostMatcher hostMatcher = HostMatcher.load(List.of("example.com"));
assertEquals(Set.of("example.com"), hostMatcher.getExactHosts());
assertEquals(Collections.emptySet(), hostMatcher.getHostParts());
}

@Test
void testLoadParts() {
HostMatcher hostMatcher = HostMatcher.load(List.of("*.example.com"));
assertEquals(Collections.emptySet(), hostMatcher.getExactHosts());
assertEquals(Set.of("example.com"), hostMatcher.getHostParts());

assertTrue(hostMatcher.matches("host.example.com"));
}

@Test
void testLoadEmptyPart() {
HostMatcher hostMatcher = HostMatcher.load(List.of("*."));
assertEquals(Collections.emptySet(), hostMatcher.getExactHosts());
assertEquals(Set.of(""), hostMatcher.getHostParts());

assertFalse(hostMatcher.matches("something"));
assertFalse(hostMatcher.matches("example.com"));
}

}

0 comments on commit 76e9cb9

Please sign in to comment.