Add a utility class for associating IP addresses with ASNs.
This commit is contained in:
parent
3056ea8cbc
commit
1160af9522
|
@ -163,6 +163,12 @@
|
|||
<version>3.12.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-csv</artifactId>
|
||||
<version>1.8</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
|
||||
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Copyright 2021 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.util;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.net.Inet4Address;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.NavigableMap;
|
||||
import java.util.Optional;
|
||||
import java.util.TreeMap;
|
||||
import org.apache.commons.csv.CSVFormat;
|
||||
import org.apache.commons.csv.CSVParser;
|
||||
import org.apache.commons.csv.CSVRecord;
|
||||
|
||||
/**
|
||||
* Allows IP->ASN lookup operations using data from https://iptoasn.com/.
|
||||
*/
|
||||
class AsnTable {
|
||||
private final NavigableMap<Long, AsnRange> asnBlocksByFirstIp;
|
||||
|
||||
private static class AsnRange {
|
||||
private final long rangeStart;
|
||||
private final long rangeEnd;
|
||||
|
||||
private final long asn;
|
||||
|
||||
private AsnRange(long rangeStart, long rangeEnd, long asn) {
|
||||
this.rangeStart = rangeStart;
|
||||
this.rangeEnd = rangeEnd;
|
||||
this.asn = asn;
|
||||
}
|
||||
|
||||
boolean contains(final long address) {
|
||||
return address >= rangeStart && address <= rangeEnd;
|
||||
}
|
||||
|
||||
long getAsn() {
|
||||
return asn;
|
||||
}
|
||||
}
|
||||
|
||||
public AsnTable(final Reader tsvReader) throws IOException {
|
||||
final TreeMap<Long, AsnRange> treeMap = new TreeMap<>();
|
||||
|
||||
try (final CSVParser csvParser = CSVFormat.TDF.parse(tsvReader)) {
|
||||
for (final CSVRecord record : csvParser) {
|
||||
final long start = Long.parseLong(record.get(0), 10);
|
||||
final long end = Long.parseLong(record.get(1), 10);
|
||||
final long asn = Long.parseLong(record.get(2), 10);
|
||||
|
||||
treeMap.put(start, new AsnRange(start, end, asn));
|
||||
}
|
||||
}
|
||||
|
||||
asnBlocksByFirstIp = treeMap;
|
||||
}
|
||||
|
||||
public Optional<Long> getAsn(final Inet4Address address) {
|
||||
final long addressAsLong = ipToLong(address);
|
||||
|
||||
return Optional.ofNullable(asnBlocksByFirstIp.floorEntry(addressAsLong))
|
||||
.filter(entry -> entry.getValue().contains(addressAsLong))
|
||||
.map(entry -> entry.getValue().getAsn());
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static long ipToLong(final Inet4Address address) {
|
||||
final ByteBuffer buffer = ByteBuffer.allocate(8);
|
||||
buffer.position(4);
|
||||
buffer.put(address.getAddress());
|
||||
|
||||
buffer.flip();
|
||||
return buffer.getLong();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright 2021 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.util;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Optional;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class AsnTableTest {
|
||||
|
||||
@Test
|
||||
void getAsn() throws IOException {
|
||||
try (final InputStreamReader reader = new InputStreamReader(getClass().getResourceAsStream("ip2asn-test.tsv"))) {
|
||||
final AsnTable asnTable = new AsnTable(reader);
|
||||
|
||||
assertEquals(Optional.of(7922L), asnTable.getAsn((Inet4Address) Inet4Address.getByName("50.79.54.1")));
|
||||
assertEquals(Optional.of(7552L), asnTable.getAsn((Inet4Address) Inet4Address.getByName("27.79.32.1")));
|
||||
assertEquals(Optional.empty(), asnTable.getAsn((Inet4Address) Inet4Address.getByName("32.79.117.1")));
|
||||
assertEquals(Optional.empty(), asnTable.getAsn((Inet4Address) Inet4Address.getByName("10.0.0.1")));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void ipToLong() throws UnknownHostException {
|
||||
assertEquals(0x00000000ffffffffL, AsnTable.ipToLong((Inet4Address) Inet4Address.getByName("255.255.255.255")));
|
||||
assertEquals(0x0000000000000001L, AsnTable.ipToLong((Inet4Address) Inet4Address.getByName("0.0.0.1")));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
458051584 458227711 7552 VN VIETEL-AS-AP Viettel Group
|
||||
843841536 844103679 7922 US COMCAST-7922 - Comcast Cable Communications, LLC
|
|
Loading…
Reference in New Issue