Merge branch 'i2pdotalt' into 'master'

i2ptunnel: Add .i2p.alt support to HTTP and SOCKS client tunnels

See merge request i2p-hackers/i2p.i2p!222
This commit is contained in:
zzz
2025-02-17 18:47:16 +00:00
5 changed files with 68 additions and 8 deletions

View File

@ -25,6 +25,7 @@ import net.i2p.app.ClientAppManager;
import net.i2p.app.Outproxy;
import net.i2p.client.I2PSession;
import net.i2p.client.LookupResult;
import net.i2p.client.naming.NamingService;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.client.streaming.I2PSocketOptions;
@ -664,7 +665,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
host = null;
break;
}
} else if(hostLowerCase.endsWith(".i2p")) {
} else if(NamingService.isI2PHost(hostLowerCase)) {
// Destination gets the hostname
destination = host;
// Host becomes the destination's "{b32}.b32.i2p" string, or "i2p" on lookup failure
@ -1279,7 +1280,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
}
} else if("i2p".equals(host)) {
clientDest = null;
} else if (destination.toLowerCase(Locale.US).endsWith(".b32.i2p")) {
} else if (NamingService.isB32Host(destination)) {
int len = destination.length();
if (len < 60 || (len >= 61 && len <= 63)) {
// 8-59 or 61-63 chars, this won't work
@ -1289,7 +1290,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
} catch (IOException ioe) {}
return;
}
if (len >= 64) {
if (NamingService.isBlindedHost(destination)) {
// catch b33 errors before session lookup
try {
BlindData bd = Blinding.decode(_context, destination);
@ -1363,7 +1364,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
header = getErrorPage("dnfp", ERR_DESTINATION_UNKNOWN);
} else if(ahelperPresent) {
header = getErrorPage("dnfb", ERR_DESTINATION_UNKNOWN);
} else if(destination.length() >= 60 && destination.toLowerCase(Locale.US).endsWith(".b32.i2p")) {
} else if (NamingService.isB32Host(destination)) {
header = getErrorPage("nols", ERR_DESTINATION_UNKNOWN);
extraMessage = _t("Destination lease set not found");
} else {
@ -1728,7 +1729,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
if(host == null) {
return null;
}
if (host.toLowerCase(Locale.US).endsWith(".b32.i2p")) {
if (NamingService.isB32Host(host)) {
return host;
}
Destination dest = _context.namingService().lookup(host);

View File

@ -16,6 +16,7 @@ import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;
import net.i2p.client.naming.NamingService;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.client.streaming.I2PSocketOptions;
import net.i2p.data.Destination;
@ -134,7 +135,7 @@ public class I2PSOCKSTunnel extends I2PTunnelClientBase {
int colon = proxy.indexOf(':');
if (colon > 0)
host = host.substring(0, colon);
if (host.endsWith(".i2p")) {
if (NamingService.isI2PHost(host)) {
proxyList.add(proxy);
} else {
String m = "Non-i2p SOCKS outproxy: " + proxy;

View File

@ -21,6 +21,7 @@ import net.i2p.I2PException;
import net.i2p.app.ClientApp;
import net.i2p.app.ClientAppManager;
import net.i2p.app.Outproxy;
import net.i2p.client.naming.NamingService;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.client.streaming.I2PSocketOptions;
import net.i2p.data.DataFormatException;
@ -211,7 +212,7 @@ class SOCKS4aServer extends SOCKSServer {
try {
String hostLowerCase = connHostName.toLowerCase(Locale.US);
if (hostLowerCase.endsWith(".i2p")) {
if (NamingService.isI2PHost(hostLowerCase)) {
Destination dest = _context.namingService().lookup(connHostName);
if (dest == null) {
try {

View File

@ -26,6 +26,7 @@ import net.i2p.I2PException;
import net.i2p.app.ClientApp;
import net.i2p.app.ClientAppManager;
import net.i2p.app.Outproxy;
import net.i2p.client.naming.NamingService;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.client.streaming.I2PSocketOptions;
import net.i2p.data.DataFormatException;
@ -459,7 +460,7 @@ class SOCKS5Server extends SOCKSServer {
try {
String hostLowerCase = connHostName.toLowerCase(Locale.US);
if (hostLowerCase.endsWith(".i2p")) {
if (NamingService.isI2PHost(hostLowerCase)) {
// Let's not do a new Dest for every request, huh?
//I2PSocketManager sm = I2PSocketManagerFactory.createManager();
//destSock = sm.connect(I2PTunnel.destFromName(connHostName), null);

View File

@ -13,6 +13,7 @@ import java.lang.reflect.Constructor;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
@ -739,6 +740,61 @@ public abstract class NamingService {
//// End new API for multiple Destinations
/**
* Is this an i2p hostname?
*
* ref: https://www.rfc-editor.org/rfc/rfc9476.html
*
* @param hostname non-null
* @return true if hostname (case insensitive) ends with .i2p or .i2p.alt
* @since 0.9.66
*/
public static boolean isI2PHost(String hostname) {
String lc = hostname.toLowerCase(Locale.US);
return lc.endsWith(".i2p") || lc.endsWith(".i2p.alt");
}
/**
* Is this a b32 hostname?
* Does NOT validate the base32 part except for length.
*
* ref: https://www.rfc-editor.org/rfc/rfc9476.html
*
* @param hostname non-null
* @return true if hostname (case insensitive) ends with .b32.i2p or .b32.i2p.alt
* and is long enough. May or may not be blinded.
* @since 0.9.66
*/
public static boolean isB32Host(String hostname) {
int len = hostname.length();
if (len < 60)
return false;
String lc = hostname.toLowerCase(Locale.US);
return lc.endsWith(".b32.i2p") ||
(len >= 64 && lc.endsWith(".b32.i2p.alt"));
}
/**
* Is this a blinded ("b33") hostname?
* Does NOT validate the base32 part except for length.
* See Blinding.decode() for full validation.
*
* ref: https://www.rfc-editor.org/rfc/rfc9476.html
*
* @param hostname non-null
* @return true if hostname (case insensitive) ends with .b32.i2p or .b32.i2p.alt
* and is long enough.
* @since 0.9.66
*/
public static boolean isBlindedHost(String hostname) {
int len = hostname.length();
if (len < 64)
return false;
String lc = hostname.toLowerCase(Locale.US);
return lc.endsWith(".b32.i2p") ||
(len >= 68 && lc.endsWith(".b32.i2p.alt"));
}
/**
* WARNING - for use by I2PAppContext only - others must use
* I2PAppContext.namingService()