Compare commits

...

8 Commits

Author SHA1 Message Date
zzz
8a216a4d7d Console: Only show restart required on /configi2cp when interface changes
Some checks failed
Daily Workflow / daily-job (push) Has been cancelled
Daily Workflow / javadoc-latest (push) Has been cancelled
Daily Workflow / build-java7 (push) Has been cancelled
Java CI / build (push) Has been cancelled
Java CI / javadoc-latest (push) Has been cancelled
Java CI / build-java7 (push) Has been cancelled
Dockerhub / docker (push) Has been cancelled
Java with IzPack Snapshot Setup / setup (push) Has been cancelled
2025-05-09 08:46:09 -04:00
zzz
6b2689bb07 I2CP: Log IP on authentication failure 2025-05-09 08:06:01 -04:00
zzz
b96b30979e SOCKS: Log IP on authentication failure 2025-05-09 07:52:01 -04:00
zzz
52dc75cc9b i2psnark: Change search of multiple tokens from OR to AND 2025-05-09 07:37:56 -04:00
zzz
9c1175fdc5 spelling 2025-05-08 10:33:50 -04:00
zzz
e8ac0dc573 i2ptunnel: Log IP on HTTP proxy authentication failure 2025-05-07 11:36:04 -04:00
zzz
7299b62aae Console: Log IP on authentication failure 2025-05-07 11:14:15 -04:00
zzz
e43fdba922 Fix link 2025-05-07 07:41:00 -04:00
14 changed files with 66 additions and 39 deletions

View File

@ -884,16 +884,21 @@ public class I2PSnarkServlet extends BasicServlet {
if (searchList == null)
return null;
List<Snark> matches = new ArrayList<Snark>(32);
loop:
for (Snark snark : snarks) {
String lcname = Normalizer.normalize(snark.getBaseName().toLowerCase(Locale.US), Normalizer.Form.NFKD);
// search for any term (OR)
for (int j = 0; j < searchList.size(); j++) {
String term = searchList.get(j);
if (lcname.contains(term)) {
matches.add(snark);
break;
}
// search for any term (OR)
//if (lcname.contains(term)) {
// matches.add(snark);
// break;
//}
// search for all terms (AND)
if (!lcname.contains(term))
continue loop;
}
matches.add(snark);
}
return matches;
}

View File

@ -477,7 +477,7 @@ public abstract class I2PTunnelHTTPClientBase extends I2PTunnelClientBase implem
return AuthResult.AUTH_GOOD;
}
}
_log.logAlways(Log.WARN, "HTTP proxy authentication failed, user: " + user);
_log.logAlways(Log.WARN, "HTTP proxy authentication failed, user: " + user + " IP: " + s.getInetAddress());
} catch (UnsupportedEncodingException uee) {
_log.error(getPrefix(requestId) + "No UTF-8 support? B64: " + authorization, uee);
} catch (ArrayIndexOutOfBoundsException aioobe) {
@ -497,7 +497,7 @@ public abstract class I2PTunnelHTTPClientBase extends I2PTunnelClientBase implem
return AuthResult.AUTH_BAD;
authorization = authorization.substring(7);
Map<String, String> args = parseArgs(authorization);
AuthResult rv = validateDigest(method, args);
AuthResult rv = validateDigest(method, args, s);
return rv;
} else {
_log.error("Unknown proxy authorization type configured: " + authRequired);
@ -508,9 +508,11 @@ public abstract class I2PTunnelHTTPClientBase extends I2PTunnelClientBase implem
/**
* Verify all of it.
* Ref: RFC 2617
*
* @param s just to log the IP on failure
* @since 0.9.4
*/
private AuthResult validateDigest(String method, Map<String, String> args) {
private AuthResult validateDigest(String method, Map<String, String> args, Socket s) {
String user = args.get("username");
String realm = args.get("realm");
String nonce = args.get("nonce");
@ -549,7 +551,7 @@ public abstract class I2PTunnelHTTPClientBase extends I2PTunnelClientBase implem
String ha1 = getTunnel().getClientOptions().getProperty(PROP_PROXY_DIGEST_PREFIX + user +
(isSHA256 ? PROP_PROXY_DIGEST_SHA256_SUFFIX : PROP_PROXY_DIGEST_SUFFIX));
if (ha1 == null) {
_log.logAlways(Log.WARN, "HTTP proxy authentication failed, user: " + user);
_log.logAlways(Log.WARN, "HTTP proxy authentication failed, user: " + user + " IP: " + s.getInetAddress());
return AuthResult.AUTH_BAD;
}
// get H(A2)
@ -559,7 +561,7 @@ public abstract class I2PTunnelHTTPClientBase extends I2PTunnelClientBase implem
String kd = ha1 + ':' + nonce + ':' + nc + ':' + cnonce + ':' + qop + ':' + ha2;
String hkd = isSHA256 ? PasswordManager.sha256Hex(kd) : PasswordManager.md5Hex(kd);
if (!response.equals(hkd)) {
_log.logAlways(Log.WARN, "HTTP proxy authentication failed, user: " + user);
_log.logAlways(Log.WARN, "HTTP proxy authentication failed, user: " + user + " IP: " + s.getInetAddress());
if (_log.shouldLog(Log.INFO))
_log.info("Bad digest auth: " + DataHelper.toString(args));
return AuthResult.AUTH_BAD;

View File

@ -99,7 +99,7 @@ class SOCKS5Server extends SOCKSServer {
in = new DataInputStream(clientSock.getInputStream());
out = new DataOutputStream(clientSock.getOutputStream());
init(in, out);
init(in, out, clientSock.getInetAddress());
if (manageRequest(in, out) == Command.UDP_ASSOCIATE)
handleUDP(in, out);
} catch (IOException e) {
@ -112,8 +112,10 @@ class SOCKS5Server extends SOCKSServer {
/**
* SOCKS5 connection initialization. This method assumes that
* SOCKS "VER" field has been stripped from the input stream.
*
* @param client just for logging
*/
private void init(DataInputStream in, DataOutputStream out) throws IOException {
private void init(DataInputStream in, DataOutputStream out, InetAddress client) throws IOException {
int nMethods = in.readUnsignedByte();
int method = Method.NO_ACCEPTABLE_METHODS;
@ -131,7 +133,7 @@ class SOCKS5Server extends SOCKSServer {
case Method.USERNAME_PASSWORD:
_log.debug("username/password authentication required");
sendInitReply(Method.USERNAME_PASSWORD, out);
verifyPassword(in, out);
verifyPassword(in, out, client);
return;
case Method.NO_AUTH_REQUIRED:
@ -148,9 +150,11 @@ class SOCKS5Server extends SOCKSServer {
/**
* Wait for the username/password message and verify or throw SOCKSException on failure
*
* @param client just for logging
* @since 0.8.2
*/
private void verifyPassword(DataInputStream in, DataOutputStream out) throws IOException {
private void verifyPassword(DataInputStream in, DataOutputStream out, InetAddress client) throws IOException {
int c = in.readUnsignedByte();
if (c != AUTH_VERSION) {
_log.logAlways(Log.WARN, "SOCKS proxy authentication failed");
@ -166,7 +170,7 @@ class SOCKS5Server extends SOCKSServer {
String u = DataHelper.getUTF8(user);
c = in.readUnsignedByte();
if (c <= 0) {
_log.logAlways(Log.WARN, "SOCKS proxy authentication failed, user: " + u);
_log.logAlways(Log.WARN, "SOCKS proxy authentication failed, user: " + u + " IP: " + client);
throw new SOCKSException("Bad authentication");
}
byte[] pw = new byte[c];
@ -179,7 +183,7 @@ class SOCKS5Server extends SOCKSServer {
String configPW = props.getProperty(psha256);
String hex = PasswordManager.sha256Hex(I2PSOCKSTunnel.AUTH_REALM, u, p);
if (configPW == null || !configPW.equals(hex)) {
_log.logAlways(Log.WARN, "SOCKS proxy authentication failed, user: " + u);
_log.logAlways(Log.WARN, "SOCKS proxy authentication failed, user: " + u + " IP: " + client);
sendAuthReply(AUTH_FAILURE, out);
throw new SOCKSException("SOCKS authorization failure");
}

View File

@ -1119,7 +1119,7 @@ public class RouterConsoleRunner implements RouterApp {
UserIdentity rv = super.login(username, credentials, request);
if (rv == null)
//_log.logAlways(net.i2p.util.Log.WARN, "Console authentication failed, webapp: " + _webapp + ", user: " + username);
_log.logAlways(net.i2p.util.Log.WARN, "Console authentication failed, user: " + username);
_log.logAlways(net.i2p.util.Log.WARN, "Console authentication failed, user: " + username + " IP: " + request.getRemoteAddr());
return rv;
}
}

View File

@ -644,13 +644,18 @@ public class ConfigClientsHandler extends FormHandler {
* @since 0.8.3
*/
private void saveInterfaceChanges() {
boolean restart = false;
Map<String, String> changes = new HashMap<String, String>();
String port = getJettyString("port");
if (port != null)
if (port != null && !port.equals(_context.getProperty(ClientManagerFacadeImpl.PROP_CLIENT_PORT, "7654"))) {
changes.put(ClientManagerFacadeImpl.PROP_CLIENT_PORT, port);
restart = true;
}
String intfc = getJettyString("interface");
if (intfc != null)
if (intfc != null && !intfc.equals(_context.getProperty(ClientManagerFacadeImpl.PROP_CLIENT_HOST, "127.0.0.1"))) {
changes.put(ClientManagerFacadeImpl.PROP_CLIENT_HOST, intfc);
restart = true;
}
String user = getJettyString("user");
String pw = getJettyString("nofilter_pw");
if (user != null && pw != null && user.length() > 0 && pw.length() > 0) {
@ -661,18 +666,28 @@ public class ConfigClientsHandler extends FormHandler {
String mode = getJettyString("mode");
boolean disabled = "0".equals(mode);
boolean ssl = "2".equals(mode);
changes.put(ConfigClientsHelper.PROP_DISABLE_EXTERNAL,
if (disabled != _context.getProperty(ConfigClientsHelper.PROP_DISABLE_EXTERNAL, false)) {
changes.put(ConfigClientsHelper.PROP_DISABLE_EXTERNAL,
Boolean.toString(disabled));
changes.put(ConfigClientsHelper.PROP_ENABLE_SSL,
restart = true;
}
if (ssl != _context.getProperty(ConfigClientsHelper.PROP_ENABLE_SSL, false)) {
changes.put(ConfigClientsHelper.PROP_ENABLE_SSL,
Boolean.toString(ssl));
restart = true;
}
changes.put(ConfigClientsHelper.PROP_AUTH,
Boolean.toString((_settings.get("auth") != null)));
boolean all = "0.0.0.0".equals(intfc) || "0:0:0:0:0:0:0:0".equals(intfc) ||
"::".equals(intfc);
changes.put(ConfigClientsHelper.BIND_ALL_INTERFACES, Boolean.toString(all));
if (all != _context.getProperty(ConfigClientsHelper.BIND_ALL_INTERFACES, false)) {
changes.put(ConfigClientsHelper.BIND_ALL_INTERFACES, Boolean.toString(all));
restart = true;
}
if (_context.router().saveConfig(changes, null)) {
addFormNotice(_t("Interface configuration saved"));
addFormNotice(_t("Restart required to take effect"));
if (restart)
addFormNotice(_t("Restart required to take effect"));
} else
addFormError(_t("Error saving the configuration (applied but not saved) - please see the error logs"));
}

View File

@ -172,7 +172,7 @@ These channels are also available outside of I2P's encrypted, anonymous network
<b>Reporting Bugs</b><br>
To report a bug, please file a ticket on <a href="http://git.idk.i2p/" target="_blank">git.idk.i2p</a> or, over clearnet, <a href="https://i2pgit.org/" target="_blank">https://i2pgit.org/</a>.
For developer-related discussions, please visit <a href="http://zzz.i2p/" target="_blank">zzz's developer forums</a> or come and visit the <a href="irc://127.0.0.1:6668/i2p-dev">developer channel</a> on I2P's IRC network.
Developers can browse source at <a href="http://git.idk.i2p/i2p-hackers/i2p.i2p" target="_blank">git.idk.i2p</a>.</li>
Developers can browse source at <a href="http://git.idk.i2p/I2P_Developers/i2p.i2p" target="_blank">git.idk.i2p</a>.</li>
<li>
<b>Get Involved!</b><br>
I2P is developed and maintained mostly through unfunded, voluntary participation by community members.

View File

@ -1,7 +1,7 @@
package net.i2p.stat;
/**
* Receive the state of the rate when its coallesced
* Receive the state of the rate when it is coalesced
*/
public interface RateSummaryListener {
/**

View File

@ -414,8 +414,9 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi
}
PasswordManager mgr = new PasswordManager(_context);
if (!mgr.checkHash(PROP_AUTH, user, pw)) {
_log.logAlways(Log.WARN, "I2CP authentication failed, user: " + user);
_runner.disconnectClient("Authorization failed, user = " + user);
String msg = "I2CP authentication failed, user: " + user + " IP: " + _runner.getAddress();
_log.logAlways(Log.WARN, msg);
_runner.disconnectClient(msg);
_authorized = false;
return false;
}

View File

@ -81,7 +81,7 @@ public class PeerProfile {
/**
* fastest 1 minute throughput, in bytes per minute, ordered with fastest
* first. this is not synchronized, as we don't *need* perfection, and we only
* reorder/insert values on coallesce
* reorder/insert values on coalesce
*/
private final float _peakThroughput[] = new float[THROUGHPUT_COUNT];
private volatile long _peakThroughputCurrentTotal;

View File

@ -23,7 +23,7 @@ import net.i2p.util.Log;
* assigned QueuePreprocessor.</li>
* <li>that QueuePreprocessor may then take off any of the TunnelGateway.Pending
* messages or instruct the TunnelGateway to offer it the messages again in
* a short while (in an attempt to coallesce them).
* a short while (in an attempt to coalesce them).
* <li>when the QueueProcessor accepts a TunnelGateway.Pending, it preprocesses
* it into fragments, forwarding each preprocessed fragment group through
* the Sender.</li>
@ -84,7 +84,7 @@ class PumpedTunnelGateway extends TunnelGateway {
/**
* Add a message to be sent down the tunnel, either sending it now (perhaps
* coallesced with other pending messages) or after a brief pause (_flushFrequency).
* coalesced with other pending messages) or after a brief pause (_flushFrequency).
* If it is queued up past its expiration, it is silently dropped
*
* This is only for OBGWs. See TPTG override for IBGWs.

View File

@ -13,7 +13,7 @@ import net.i2p.util.SimpleByteCache;
/**
* Do the simplest thing possible for preprocessing - for each message available,
* turn it into the minimum number of fragmented preprocessed blocks, sending
* each of those out. This does not coallesce message fragments or delay for more
* each of those out. This does not coalesce message fragments or delay for more
* optimal throughput.
*
* See FragmentHandler Javadoc for tunnel message fragment format

View File

@ -40,7 +40,7 @@ public abstract class TunnelCreatorConfig implements TunnelInfo {
// Fastest 1 minute throughput, in bytes per minute, ordered with fastest first.
//private final double _peakThroughput[] = new double[THROUGHPUT_COUNT];
private long _peakThroughputCurrentTotal;
private long _peakThroughputLastCoallesce = System.currentTimeMillis();
private long _peakThroughputLastCoalesce = System.currentTimeMillis();
private Hash _blankHash;
private SessionKey[] _ChaReplyKeys;
private byte[][] _ChaReplyADs;
@ -176,11 +176,11 @@ public abstract class TunnelCreatorConfig implements TunnelInfo {
_verifiedBytesTransferred += bytes;
_peakThroughputCurrentTotal += bytes;
long now = System.currentTimeMillis();
long timeSince = now - _peakThroughputLastCoallesce;
long timeSince = now - _peakThroughputLastCoalesce;
if (timeSince >= 60*1000) {
long tot = _peakThroughputCurrentTotal;
int normalized = (int) (tot * 60d*1000d / timeSince);
_peakThroughputLastCoallesce = now;
_peakThroughputLastCoalesce = now;
_peakThroughputCurrentTotal = 0;
if (_context != null) {
// skip ourselves

View File

@ -20,7 +20,7 @@ import net.i2p.util.SimpleTimer2;
* assigned QueuePreprocessor.</li>
* <li>that QueuePreprocessor may then take off any of the TunnelGateway.Pending
* messages or instruct the TunnelGateway to offer it the messages again in
* a short while (in an attempt to coallesce them).
* a short while (in an attempt to coalesce them).
* <li>when the QueueProcessor accepts a TunnelGateway.Pending, it preprocesses
* it into fragments, forwarding each preprocessed fragment group through
* the Sender.</li>
@ -78,7 +78,7 @@ abstract class TunnelGateway {
/**
* Add a message to be sent down the tunnel, either sending it now (perhaps
* coallesced with other pending messages) or after a brief pause (_flushFrequency).
* coalesced with other pending messages) or after a brief pause (_flushFrequency).
* If it is queued up past its expiration, it is silently dropped
*
* UNUSED - see overrides

View File

@ -147,7 +147,7 @@ class TunnelParticipant {
/****
private int _periodMessagesTransferred;
private long _lastCoallesced = System.currentTimeMillis();
private long _lastCoalesced = System.currentTimeMillis();
****/
/**
@ -161,12 +161,12 @@ class TunnelParticipant {
private void incrementThroughput(Hash prev) {
if (true) return;
long now = System.currentTimeMillis();
long timeSince = now - _lastCoallesced;
long timeSince = now - _lastCoalesced;
if (timeSince >= 60*1000) {
int amount = 1024 * _periodMessagesTransferred;
int normalized = (int)((double)amount * 60d*1000d / (double)timeSince);
_periodMessagesTransferred = 0;
_lastCoallesced = now;
_lastCoalesced = now;
_context.profileManager().tunnelDataPushed1m(prev, normalized);
} else {
_periodMessagesTransferred++;