Can I check remote address connecting to a ServerSocket before accepting?

I have a ServerSocket for which I'd like to implement an IP filter, using an allow or deny list to control which IP addresses can connect. After accepting the connection, I check the remote address on the Socket that is created, and apply the filter. However, if I close the connection to a denied address, the client sees that the connection was accpeted, but then it throws a SocketException when it tries to write to it.

That accomplishes the purpose of the filter, but it doesn't seem like good behavior from the client's perspective. I'd like to implement a ServerSocket that doesn't even accept the connection if the remote address is not permitted. Is there any way to do that?

[702 byte] By [MidnightJavaa] at [2007-11-26 17:14:08]
# 1
Can't be done in application code. Use a firewall.
ejpa at 2007-7-8 23:42:06 > top of Java-index,Core,Core APIs...
# 2
> Can't be done in application code. Use a firewall.Could the firewall do the things the OP requires, which are not fully described yet except 'no exception on client side'?
hiwaa at 2007-7-8 23:42:06 > top of Java-index,Core,Core APIs...
# 3

There is no way to implement a filter mechanism with java.net.ServerSocket. The only way to block the clients request it to use a firewall as suggested. In this case the client may get a java.net.ConnectException. The exact Exception seen on the client will depend on how the firewall handles the clients connection request. It may simply discard it, in which case the client will eventually timeout.

chegara at 2007-7-8 23:42:06 > top of Java-index,Core,Core APIs...
# 4

It's not the type of Exception that concerns me, just whether the Exception or other manifestation of the filter being applied occurs during attempted connection setup rather than when trying to write to a connection that was originally accepted.

A firewall is a good solution for me. But I'm writing some code for distribution that will listen on a designated port and accept data for the clipboard or possibly to be written to a file. II wanted to give prospective users the ability to set up additional protection in addition to firewall. It seems that other languages can do this. Consider, for example, Filezilla Server (FTP server) which has a filter that works the way I described above.

It's clear to me it can't be done with java.net.ServerSocket. I was hoping that someone had developed an alternative ServerSocket implementation with a filter, sort of like commons-io provides alternative implementations of java.io capabilities.

MidnightJavaa at 2007-7-8 23:42:06 > top of Java-index,Core,Core APIs...
# 5
Why not write a connection accepted/refused message to the client and then carry on (or close the socket/streams at both ends)?
duckbilla at 2007-7-8 23:42:06 > top of Java-index,Core,Core APIs...
# 6

> Why not write a connection accepted/refused message

> to the client and then carry on (or close the

> socket/streams at both ends)?

I'm not sure I understand your suggestion. When ServerSocket.accept() returns by providing a Socket object, that is the first time the server code can determine the IP address of the client and apply an IP filter. However, the connection has already been established at this point, so it's not possible to make an accept/refuse decision for the connection based on the client IP address. By the time the server code sees the IP address, the connection has already been accepted, and the only recourse is to close the connection from the server (by calling close() on the Socket object that was returned), and the client will then throw an exception with the message saying that the software closed the connection.

Legitimate users trying to connect may interpret this as a software problem, if they don't know any better. Intruders will discover from this behavior that the port is open through the firewall, and may conclude that IP filtering is being applied, and if they have some idea of what IP addresses are allowed, they could easily spoof them. Or they could keep trying, hoping to catch the server when the IP filtering is turned off.

It would be better to mimic the filtering behavior of a firewall, whereby the connection is not established. Then the client would report that it could not establish the connection, and the user would be more likely to look into whether the port is open or IP filtering is occurring, rather than thinking there is a software problem. And the intruder would conclude that the port is not open and go somewhere else.

I would need a different implementation of ServerSocket to do this. I checked jakarta commons net, but that only provides client side utilities. I'm currently untangling the source code of java.net.ServerSocket to see how difficult it will be to override the accept() method to provide filtering behavior. This seems like a useful thing, and I thought perhaps someone had already done so. Or perhaps someone can tell me why this is not a good idea.

Message was edited by:

MidnightJava

MidnightJavaa at 2007-7-8 23:42:06 > top of Java-index,Core,Core APIs...
# 7

> It seems that other languages can do this. Consider, for example,

> Filezilla Server (FTP server) which has a filter that

> works the way I described above.

No they can't. It can't be done in TCP/IP because of the existence of the backlog queue. A connection may already have been accepted by TCP/IP before you even call accept().

If Filezilla really did this it would have to implement part of TCP/IP itself. I can't find anything in its documentation to justify this claim.

Use a firewall.

ejpa at 2007-7-8 23:42:06 > top of Java-index,Core,Core APIs...
# 8

Yes I stand corrected. I was remembering the connection being rejected with FIlezilla server when IP filtering was applied; but apparently I was remembering what happened at the FTP layer. I ran a test and captured the TCP segments. TCP completes the connection set up, and FTP sends a 550 Response, No connections allowed from your IP. Then the server closes the TCP connection.

You're right that the existence of the backlog queue makes it fruitless to try to implement this behavior in Java. Doing IP filtering with the app, as a backup to simple firewall implementations, still makes sense to me; but I'll have to settle for accepting and then closing the connection when initiated from invalid IPs.

MidnightJavaa at 2007-7-8 23:42:06 > top of Java-index,Core,Core APIs...
# 9

>I'm not sure I understand your suggestion.

Client->connect()

Server->Accept()

Both ends init streams

Server sends OK/NOK

Client reads OK/NOK

NOK->close() both ends, and client prints "connection refused"

OK->continue

But I guess you're looking for something different.

Jukka

duckbilla at 2007-7-8 23:42:06 > top of Java-index,Core,Core APIs...
# 10
A simple close would accomplish that.
ejpa at 2007-7-8 23:42:06 > top of Java-index,Core,Core APIs...
# 11

> Client->connect()

> Server->Accept()

> Both ends init streams

> Server sends OK/NOK

> Client reads OK/NOK

> NOK->close() both ends, and client prints "connection

> refused"

> OK->continue

> Jukka

I see your point now. The OK/NOK signal addresses my stated desire for the client to report "connection refused" when the filter is applied at the server. This is essentially a crude facsimile of how FTP handles it, as illustrated in my earlier post.

I guess this would work, although I'd change the message to something similar to the FTP 550 message, to avoid semantic confusion and make it clear at what level the connection was refused. But I agree with ejp that it's simpler to just have the server close the connection. When I handle the SocketException at the client I tell the user to make sure the port is open and check the IP filter settings on the server. A more complex implementation would perhaps be worth it if I really could mimic the firewall behavior, but I think this is sufficient for my purpose.

Thanks for the suggestion; and thanks, ejp, for making the case for a separation of concerns between the firewall and the server application code.

MidnightJavaa at 2007-7-8 23:42:06 > top of Java-index,Core,Core APIs...
# 12
> Can't be done in application code. Use a firewall.Can be done using WinSock, but this will not help much in Java code...
Michael.Nazarov@sun.coma at 2007-7-8 23:42:06 > top of Java-index,Core,Core APIs...