Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
5ff82ed
added SOCKS5 support for DNS over tcp and udp (first working version)
Thomas-Internetx Oct 2, 2024
5a41225
refactored code for udp associate into IoClient
Thomas-Internetx Oct 3, 2024
bee0c76
added user/pwd authentication and refactored some of the code
Thomas-Internetx Oct 18, 2024
2a1192c
redo code changes in SimpleResolver and the IoClients
Thomas-Internetx Dec 5, 2024
80dfcb6
implemented SOCKS5 requests in an async way and added requested changes
Thomas-Internetx Dec 5, 2024
156c797
clean up
Thomas-Internetx Dec 5, 2024
3dae148
integration of SOCKS5 with the current selector thread and timeout im…
Thomas-Internetx Jan 10, 2025
8efe515
channel pool for UDP associate
tw-datascientist Jan 12, 2025
f9c1feb
integration the UDP channel pool
Thomas-Internetx Jan 12, 2025
9d0df8b
clean up of idle udp associate connections
Thomas-Internetx Jan 17, 2025
44f4415
further cleanup of the NioSocksHandler
Thomas-Internetx Jan 18, 2025
4cfaf31
better error handling
Thomas-Internetx Jan 18, 2025
07a6977
cleanup
Thomas-Internetx Jan 18, 2025
c365e36
adjustments for the socks5 handshake future
Thomas-Internetx Jan 18, 2025
260c4d5
Make compatible with Java 8
Thomas-Internetx Jan 18, 2025
02c3168
adjusting changes to upstream
Thomas-Internetx Jan 25, 2025
588df3d
clean up
Thomas-Internetx Jan 25, 2025
46a1b24
added testcontainer
Thomas-Internetx Jan 25, 2025
66a1e1d
adjusted corefile path
Thomas-Internetx Jan 25, 2025
ba1ea1c
adjusted corefile path
Thomas-Internetx Jan 25, 2025
baf40f2
adjusted docker compose setup
Thomas-Internetx Jan 25, 2025
ba11e90
adjusted docker compose setup
Thomas-Internetx Jan 25, 2025
8b71b09
implemented simple test for DNS over Socks
Thomas-Internetx Jan 25, 2025
c0ffa87
implemented simple test for DNS over Socks
Thomas-Internetx Jan 25, 2025
f36df78
implemented simple test for DNS over Socks
Thomas-Internetx Jan 25, 2025
240d206
implemented simple test for DNS over Socks
Thomas-Internetx Jan 25, 2025
c807b02
implemented simple test for DNS over Socks
Thomas-Internetx Jan 25, 2025
d0f3460
implemented simple test for DNS over Socks
Thomas-Internetx Jan 25, 2025
1f88de9
adjusting changes to upstream
Thomas-Internetx Jan 25, 2025
02ef998
adjusting changes to upstream
Thomas-Internetx Jan 25, 2025
3970b97
further clean up
Thomas-Internetx Jan 25, 2025
00bdea2
further clean up
Thomas-Internetx Jan 25, 2025
688fe6d
further clean up
Thomas-Internetx Jan 25, 2025
e94d15c
further clean up
Thomas-Internetx Jan 25, 2025
b621b32
improved comment for DST.ADDR and DST.PORT in the SOCKS handshake
Thomas-Internetx Jan 26, 2025
a12d004
improved comment for static registrationQueue and channelMap
Thomas-Internetx Jan 26, 2025
a8be13b
improved comment for response to future mapping
Thomas-Internetx Jan 26, 2025
fe2a79e
added step for docker setup
Thomas-Internetx Jan 26, 2025
73c0db0
set DOCKER_HOST
Thomas-Internetx Jan 26, 2025
99455be
reduced logs for Testcontainers
Thomas-Internetx Jan 26, 2025
fb3f015
fixed format violations
Thomas-Internetx Jan 26, 2025
938e726
fixed format violations
Thomas-Internetx Jan 26, 2025
b255bc3
try to make Testcontainers work with windows https://java.testcontain…
Thomas-Internetx Jan 26, 2025
10141bc
try to make Testcontainers work with windows https://java.testcontain…
Thomas-Internetx Jan 26, 2025
7caf075
try to make Testcontainers work with windows https://java.testcontain…
Thomas-Internetx Jan 26, 2025
fd301ba
try to make Testcontainers work with windows https://java.testcontain…
Thomas-Internetx Jan 26, 2025
3b62593
try to make Testcontainers work with windows https://java.testcontain…
Thomas-Internetx Jan 26, 2025
b97610d
try to make Testcontainers work with windows https://java.testcontain…
Thomas-Internetx Jan 26, 2025
4008b84
try to make Testcontainers work with windows https://java.testcontain…
Thomas-Internetx Jan 26, 2025
d416209
try to make Testcontainers work with windows https://java.testcontain…
Thomas-Internetx Jan 26, 2025
7b37e19
removed differentiation of remote address for SocksUdpAssociateChanne…
Thomas-Internetx Feb 9, 2025
d8dde40
fixed style
Thomas-Internetx Feb 10, 2025
be7245c
fixed style
Thomas-Internetx Feb 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
redo code changes in SimpleResolver and the IoClients
  • Loading branch information
Thomas-Internetx committed Jan 26, 2025
commit 2a1192c822c90d3c7a4809a6daf766f2b952317d
23 changes: 0 additions & 23 deletions src/main/java/org/xbill/DNS/DefaultIoClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,6 @@ public CompletableFuture<byte[]> sendAndReceiveTcp(
return tcpIoClient.sendAndReceiveTcp(local, remote, query, data, timeout);
}

@Override
public CompletableFuture<byte[]> sendAndReceiveTcp(
InetSocketAddress local,
InetSocketAddress remote,
Socks5Proxy proxy,
Message query,
byte[] data,
Duration timeout) {
return tcpIoClient.sendAndReceiveTcp(local, remote, proxy, query, data, timeout);
}

@Override
public CompletableFuture<byte[]> sendAndReceiveUdp(
InetSocketAddress local,
Expand All @@ -54,16 +43,4 @@ public CompletableFuture<byte[]> sendAndReceiveUdp(
Duration timeout) {
return udpIoClient.sendAndReceiveUdp(local, remote, query, data, max, timeout);
}

@Override
public CompletableFuture<byte[]> sendAndReceiveUdp(
InetSocketAddress local,
InetSocketAddress remote,
Socks5Proxy proxy,
Message query,
byte[] data,
int max,
Duration timeout) {
return udpIoClient.sendAndReceiveUdp(local, remote, proxy, query, data, max, timeout);
}
}
23 changes: 1 addition & 22 deletions src/main/java/org/xbill/DNS/NioTcpClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,6 @@ private void processPendingRegistrations() {
if (!state.channel.isConnected()) {
state.channel.register(selector, SelectionKey.OP_CONNECT, state);
} else {
if (state.channel.keyFor(selector) == null) {
state.channel.register(selector, SelectionKey.OP_CONNECT, state);
}
state.channel.keyFor(selector).interestOps(SelectionKey.OP_WRITE);
}
} catch (IOException e) {
Expand Down Expand Up @@ -288,21 +285,10 @@ private static class ChannelKey {
final InetSocketAddress remote;
}

@Override
public CompletableFuture<byte[]> sendAndReceiveTcp(
InetSocketAddress local,
InetSocketAddress remote,
Message query,
byte[] data,
Duration timeout) {
return this.sendAndReceiveTcp(local, remote, null, query, data, timeout);
}

@Override
public CompletableFuture<byte[]> sendAndReceiveTcp(
InetSocketAddress local,
InetSocketAddress remote,
Socks5Proxy proxy,
Message query,
byte[] data,
Duration timeout) {
Expand All @@ -323,14 +309,7 @@ public CompletableFuture<byte[]> sendAndReceiveTcp(
c.bind(local);
}

if (proxy != null) {
c.configureBlocking(true);
c.connect(proxy.getProxyAddress());
proxy.socks5TcpHandshake(c, remote);
} else {
c.connect(remote);
}
c.configureBlocking(false);
c.connect(remote);
return new ChannelState(c);
} catch (IOException e) {
if (c != null) {
Expand Down
73 changes: 15 additions & 58 deletions src/main/java/org/xbill/DNS/NioUdpClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import java.nio.channels.DatagramChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.security.SecureRandom;
import java.time.Duration;
import java.util.Iterator;
Expand Down Expand Up @@ -64,7 +63,7 @@ private void processPendingRegistrations() {

try {
log.trace("Registering OP_READ for transaction with id {}", t.id);
t.udpChannel.register(selector(), SelectionKey.OP_READ, t);
t.channel.register(selector(), SelectionKey.OP_READ, t);
t.send();
} catch (IOException e) {
t.completeExceptionally(e);
Expand All @@ -88,19 +87,17 @@ private class Transaction implements KeyProcessor {
private final byte[] data;
private final int max;
private final long endTime;
private final DatagramChannel udpChannel;
private final SocketChannel tcpChannel;
private final Socks5Proxy proxy;
private final DatagramChannel channel;
private final CompletableFuture<byte[]> f;

void send() throws IOException {
ByteBuffer buffer = ByteBuffer.wrap(data);
verboseLog(
"UDP write: transaction id=" + id,
udpChannel.socket().getLocalSocketAddress(),
udpChannel.socket().getRemoteSocketAddress(),
channel.socket().getLocalSocketAddress(),
channel.socket().getRemoteSocketAddress(),
data);
int n = udpChannel.send(buffer, udpChannel.socket().getRemoteSocketAddress());
int n = channel.send(buffer, channel.socket().getRemoteSocketAddress());
if (n == 0) {
throw new EOFException(
"Insufficient room for the datagram in the underlying output buffer for transaction "
Expand Down Expand Up @@ -141,14 +138,6 @@ public void processReadyKey(SelectionKey key) {
keyChannel.socket().getRemoteSocketAddress(),
resultingData);
silentDisconnectAndCloseChannel();
if (proxy != null && tcpChannel != null) {
resultingData = proxy.removeUdpHeader(resultingData);
try {
tcpChannel.close();
} catch (IOException e) {
// ignore, we either already have everything we need or can't do anything
}
}
f.complete(resultingData);
pendingTransactions.remove(this);
}
Expand All @@ -160,64 +149,32 @@ private void completeExceptionally(Exception e) {

private void silentDisconnectAndCloseChannel() {
try {
udpChannel.disconnect();
channel.disconnect();
} catch (IOException e) {
// ignore, we either already have everything we need or can't do anything
} finally {
NioUdpClient.silentCloseChannel(udpChannel);
NioUdpClient.silentCloseChannel(channel);
}
}
}

@Override
public CompletableFuture<byte[]> sendAndReceiveUdp(
InetSocketAddress local,
InetSocketAddress remote,
Message query,
byte[] data,
int max,
Duration timeout) {
return sendAndReceiveUdp(local, remote, null, query, data, max, timeout);
}

@Override
public CompletableFuture<byte[]> sendAndReceiveUdp(
InetSocketAddress local,
InetSocketAddress remote,
Socks5Proxy proxy,
Message query,
byte[] data,
int max,
Duration timeout) {
long endTime = System.nanoTime() + timeout.toNanos();
CompletableFuture<byte[]> f = new CompletableFuture<>();
DatagramChannel udpChannel = null;
SocketChannel tcpChannel = null;
DatagramChannel channel = null;
try {
final Selector selector = selector();
channel = DatagramChannel.open();
channel.configureBlocking(false);

// SOCKS5 handshake to set up the UDP association
if (proxy != null) {
data = proxy.addUdpHeader(data, remote);
try {
tcpChannel = SocketChannel.open();
if (local != null) {
tcpChannel.bind(local);
}
tcpChannel.connect(proxy.getProxyAddress());
remote = proxy.socks5UdpAssociateHandshake(tcpChannel);
} catch (IOException e) {
return new CompletableFuture<>().thenComposeAsync(in -> {
f.completeExceptionally(new WireParseException("Error in Udp Associate SOCKS5 handshake", e));
return f;
});
}
}

udpChannel = DatagramChannel.open();
udpChannel.configureBlocking(false);

Transaction t = new Transaction(query.getHeader().getID(), data, max, endTime, udpChannel, tcpChannel, proxy, f);
Transaction t = new Transaction(query.getHeader().getID(), data, max, endTime, channel, f);
if (local == null || local.getPort() == 0) {
boolean bound = false;
for (int i = 0; i < 1024; i++) {
Expand All @@ -236,7 +193,7 @@ public CompletableFuture<byte[]> sendAndReceiveUdp(
addr = new InetSocketAddress(local.getAddress(), port);
}

udpChannel.bind(addr);
channel.bind(addr);
bound = true;
break;
} catch (SocketException e) {
Expand All @@ -250,16 +207,16 @@ public CompletableFuture<byte[]> sendAndReceiveUdp(
}
}

udpChannel.connect(remote);
channel.connect(remote);
pendingTransactions.add(t);
registrationQueue.add(t);
selector.wakeup();
} catch (IOException e) {
silentCloseChannel(udpChannel);
silentCloseChannel(channel);
f.completeExceptionally(e);
} catch (Throwable e) {
// Make sure to close the channel, no matter what, but only handle the declared IOException
silentCloseChannel(udpChannel);
silentCloseChannel(channel);
throw e;
}

Expand Down
34 changes: 8 additions & 26 deletions src/main/java/org/xbill/DNS/SimpleResolver.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.nio.channels.SocketChannel;
import java.time.Duration;
import java.util.List;
import java.util.Objects;
Expand All @@ -20,8 +19,6 @@
import lombok.extern.slf4j.Slf4j;
import org.xbill.DNS.io.DefaultIoClientFactory;
import org.xbill.DNS.io.IoClientFactory;
import org.xbill.DNS.io.TcpIoClient;
import org.xbill.DNS.io.UdpIoClient;

/**
* An implementation of Resolver that sends one query to one server. SimpleResolver handles TCP
Expand All @@ -43,7 +40,6 @@ public class SimpleResolver implements Resolver {

private InetSocketAddress address;
private InetSocketAddress localAddress;
private Socks5Proxy proxy;
private boolean useTCP;
private boolean ignoreTruncation;
private OPTRecord queryOPT = new OPTRecord(DEFAULT_EDNS_PAYLOADSIZE, 0, 0, 0);
Expand Down Expand Up @@ -103,11 +99,6 @@ public SimpleResolver(InetSocketAddress host) {
address = Objects.requireNonNull(host, "host must not be null");
}

/** Creates a SimpleResolver that will query the specified host via the specified SOCKS5 proxy */
public SimpleResolver(Socks5Proxy socks5Proxy) {
proxy = Objects.requireNonNull(socks5Proxy, "proxy must not be null");
}

/** Creates a SimpleResolver that will query the specified host */
public SimpleResolver(InetAddress host) {
Objects.requireNonNull(host, "host must not be null");
Expand Down Expand Up @@ -396,25 +387,16 @@ CompletableFuture<Message> sendAsync(Message query, boolean forceTcp, Executor e
}

CompletableFuture<byte[]> result;
SocketChannel c = null;
if (tcp) {
TcpIoClient tcpClient = ioClientFactory.createOrGetTcpClient();
if (proxy != null) {
localAddress = proxy.getLocalAddress();
address = proxy.getRemoteAddress();
result = tcpClient.sendAndReceiveTcp(localAddress, address, proxy, query, out, timeoutValue);
} else {
result = tcpClient.sendAndReceiveTcp(localAddress, address, query, out, timeoutValue);
}
result =
ioClientFactory
.createOrGetTcpClient()
.sendAndReceiveTcp(localAddress, address, query, out, timeoutValue);
} else {
UdpIoClient udpClient = ioClientFactory.createOrGetUdpClient();
if (proxy != null) {
localAddress = proxy.getLocalAddress();
address = proxy.getRemoteAddress();
result = udpClient.sendAndReceiveUdp(localAddress, address, proxy, query, out, udpSize, timeoutValue);
} else {
result = udpClient.sendAndReceiveUdp(localAddress, address, query, out, udpSize, timeoutValue);
}
result =
ioClientFactory
.createOrGetUdpClient()
.sendAndReceiveUdp(localAddress, address, query, out, udpSize, timeoutValue);
}

return result.thenComposeAsync(
Expand Down
9 changes: 0 additions & 9 deletions src/main/java/org/xbill/DNS/io/TcpIoClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import java.util.concurrent.CompletableFuture;
import org.xbill.DNS.Message;
import org.xbill.DNS.Resolver;
import org.xbill.DNS.Socks5Proxy;

/**
* Serves as an interface from a {@link Resolver} to the underlying mechanism for sending bytes over
Expand All @@ -33,12 +32,4 @@ CompletableFuture<byte[]> sendAndReceiveTcp(
Message query,
byte[] data,
Duration timeout);

CompletableFuture<byte[]> sendAndReceiveTcp(
InetSocketAddress local,
InetSocketAddress remote,
Socks5Proxy proxy,
Message query,
byte[] data,
Duration timeout);
}
10 changes: 0 additions & 10 deletions src/main/java/org/xbill/DNS/io/UdpIoClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import java.util.concurrent.CompletableFuture;
import org.xbill.DNS.Message;
import org.xbill.DNS.Resolver;
import org.xbill.DNS.Socks5Proxy;

/**
* Serves as an interface from a {@link Resolver} to the underlying mechanism for sending bytes over
Expand Down Expand Up @@ -35,13 +34,4 @@ CompletableFuture<byte[]> sendAndReceiveUdp(
byte[] data,
int max,
Duration timeout);

CompletableFuture<byte[]> sendAndReceiveUdp(
InetSocketAddress local,
InetSocketAddress remote,
Socks5Proxy proxy,
Message query,
byte[] data,
int max,
Duration timeout);
}