My game server is now accepting sockets from every one. But how can I block specific IPs from attack? You know, if they would like to crash my server or something. I'm using SFML library, C++.
With TCP, when your program (or the library you are using) calls accept(2), the second argument is an output which tells you the client's address.
With UDP there are no connections, but there is recvfrom(2), which just like accept(2), gives you the peer's address. So you can ignore the peers you don't like.
Or you can run your server behind some sort of firewall appliance and add rules there, or use iptables or similar as a software firewall on the host machine.
In SFML you have SocketTCP::Accept and SocketUDP::Receive, both of which will give you the peer's address if you pass an empty address as an argument.
I don't know of any specific method for blocking some ips, but you can surely reject the request (probably connection request in your case) after determining the originating ip. Maintain a list of blocked ip (or BlackListed ip) (make it configurable as well for easier additions/deletions) and reject the request if it is coming from one of the Black Listed ips.
Under Windows, WinSock 2.x has an optional callback parameter for WSAAccept() that can be used to conditionally accept/reject connection requests. Client IP/Port is one of the available parameters.
Related
I'm running a server (say on port 50000). Any new request is accepted and a random port is assigned by OS each time. I want to manually assign the port number instead of system doing it randomly for me.
The main reason for this is I'm trying to do some multicast thing based on port number. I'm planning to assign few clients on same port. Next slot of clients on another port and so on.
Any idea?
A TCP socket is identified by a tuple of client-side IP/Port and server-side IP/Port pairs. The server-side IP/Port is decided by calling bind() before listen(). The client IP/Port is decided explicitly by calling bind() before connect(), or implicitly by omitting bind() and letting connect() decide. When a connection is accepted by accept(), it is assigned the client-side IP/Port that made it and the server-side IP/Port that accepted it.
The only random option available here is on the client side. It can call connect() without a preceding bind(), or it can call bind() with a zero IP/Port. In either case, the OS chooses an appropriate network adapter and assigns its IP if not explicitly stated, and assigns a random available ephemeral port if not explicitly stated. Calling bind() allows the client to assign either/both of those values if desired. bind() is not typically used on the client side in most situations, but it is allowed when needed when dealing with specific protocol requirements or firewall/router issues.
Tracking clients by Port alone is not good enough. You need to track the full tuple instead, or at least the client-side IP/port pair of the tuple. Clients from the same network would be using the same client IP but different Ports, but clients from different networks would be using different client IPs and could be using the same client Port, and that is perfectly OK. So using Port alone may find the wrong client from the wrong network. You need to take the client IP into account as well.
When the server accepts a connection, the server has no control over changing the values of the tuple. The OS needs the values to be predictable so it can route packets correctly. When you want to send a packet to a specific client, you need to know both client IP and Port.
If you want to have different server-side IP/Port values in the tuples of accepted connections, the only option is to open multiple listening sockets that are bound with the desired server-side values.
First, I want to give thanks for that amazing lib! I love it. A client is connecting himself to a server. The server should save the IP and do stuff with it later on (I really need the IP). I found that answer: http://lists.zeromq.org/pipermail/zeromq-dev/2010-September/006381.html but I don't understand how I get the IP out of the message (a XREP)... I think I am only able to read the ID, but the IP is managed internally by 0MQ. His second solution suggests to send the IP as part of the message, but I don't understand how to get the "public"-IP. I found that post: Get TCP address information in ZeroMQ
is pass bind a service to an ephemeral port, get a full connection endpoint ("tcp://ipaddress:port")
I don't get how this works. Does he mean something like a web-service?
In my opinion, it would be best to get the IP out of 0MQ (it has the IP already). I would even adjust 0MQ for that, if somebody could point to the place where the IP is saved, couldn't find it. The socket types are not that important, at the moment. I would prefer smth REQ-REP like. Thank you!
Summary:
TL;DR answer to your question is: you can't get IP address of the peer that sent a message, using ZeroMQ API.
Explanation:
ZeroMQ does not expose peer IP address because it is irrelevant for the message based communication that ZeroMQ is designed for. When it is possible for ZeroMQ to get IP address of client that is connecting to server (in example using method described here), it is useless. For a longer explanation here is how it works inside ZeroMQ and any other server implementation.
Server side of the connection does not handle connected clients by the means of the hashtable that maps IP to client, but by keeping track of connected "sockets" (socket descriptors) - when a server accepts (using accept()) a connection, it receives from operating system socket descriptor to use to communicate with connected peer. All server has to do is keep that descriptor around to read() from and write() to that client. Another client that connects to server receives another socket descriptor.
To summarize: even if ZeroMQ would be able to provide you with IP of connected peer, you should not depend on it. ZeroMQ hides from you connection management so you can focus on messaging. Connection management includes reconnections, which may result in a change of IP without changing the actual ZeroMQ socket connected on the other side.
So here's an example of why you might want to get the ip address a message was delivered from: we have a server whose job it is to synchronize updates onto occasionally-connected clients (think mobile devices here, though this is an extreme example of a mobile deivce.)
When the mobile unit comes onto the network, it sends a list of it's firmware files to the server via a dealer-router connection. The server has a list of all applicable firmware files; if the client needs an update it will initiate an update via a separate mechanism.
Since the IPs for the devices can (and do) change, we need to know the IP address associated with the mobile device FOR THIS CONNECTION, i.e. right now.
Yes, we absolutely can have the client send it's IP address in the message, but that's a waste of another n bytes of valuable satellite air time, and while not pure evil, is sure annoying. Zmq already has this information, if it didn't have it, it wouldn't be able to generate replies. The address is in the socket data, there's no reason the message couldn't (optionally, for all you guys who use wired networks and think disconnects are the exception) include a reference to the socket structure so you can get the address out of it. Other than pedantic religiosity, which is far too common in zmq.
The way ZeroMQ is designed there's no information provided on the remote IP. As far as I know you have to manage this through your application by sending that information as a message of some sort.
The messages themselves use an IP-agnostic ID which has more to do with the instance of ZeroMQ running than any particular interface. This is because there may be more than one transport method and interface connecting the two instances.
I'm studing c++ socket programming...
The server program binds to a socket and starts listening for connection requests...ok now how can I list the IP addreses of the listened requests?
I know I can get the IP addresses after accepting the connections but lets say I don't wanna accept a connection from an specific IP address...
On Windows only, you can use the conditional callback feature of WinSock2's WSAAccept() function to access client information before accepting a connection, and to even reject the connection before it is accepted.
This can't be done in terms of the standard socket API. On all platforms I know, the system actually accepts the connection (i.e. responds with SYN+ACK TCP datagram) before the application has a chance to monitor the pending request.
For optimum performance, this would be solved by filtering in the network stack, but the details of doing that will depend on the operating system (this is not part of the socket interface and your application may generally not even have the rights to configure your network stack this way.)
The other opportunity is after the accept, by which time the connection is already accepted (CONNECT ACK) on TCP level.
I don't think you can do it in the middle phase where you would prefer that. That however would not be very different from doing it after accept anyway.
In C++ using Windows32 using windows socket library using UDP is there a way to give a client routing information to another client to establish a connection between clients without having to route through the server
Clarification:
server - waits for computers and gives routing info - a detached server
client - sends a ack request and waits for routing info - a normal user computer
but ok so its not posible to give routing info to clients to interconnect clients without requiring the data to be forwarded through the server?
Short answer: no.
Long answer: No matter what information you include in your UDP packet, at the transport layer it's just another IP packet, and your NIC will slap the appropriate headers on it and send it on its way. Unless the hosts are directly connected to each other, the network topology will dictate how many hops (routers/switches) it has to make to get there.
Addendum:
I'm not sure what you mean by server (I read it as "router" initially, but you could just as easily have been talking about a Domain Name Server (DNS)). If you are trying to avoid DNS lookup, you can easily do this by providing an IP address directly (assuming you know it). However, DNS lookup is a one-time process--once the IP address is known, the DNS host is not involved in routing your UDP packets in any way.
Short answer: no
Long answer: yes --- but you have to use IPPROTO_IP, not IPPROTO_UDP. Use IP_OPTIONS option in setsockopt() to set source routing.
Is there an existing Linux/POSIX C/C++ library or example code for how to rebind a socket from one physical interface to another?
For example, I have ping transmitting on a socket that is associated with a physical connection A and I want to rebind that socket to physical connection B and have the ping packets continue being sent and received on connection B (after a short delay during switch-over).
I only need this for session-less protocols.
Thank you
Update:
I am trying to provide failover solution for use with PPP and Ethernet devices.
I have a basic script which can accomplish 90% of the functionality through use of iptables, NAT and routing table.
The problem is when the failover occurs, the pings continue being sent on the secondary connection, however, their source IP is from the old connection.
I've spoken with a couple of people who work on commercial routers and their suggestion is to rebind the socket to the secondary interface.
Update 2:
I apologise for not specifying this earlier. This solution will run on a router. I cannot change the ping program because it will run on the clients computer. I used ping as just an example, any connection that is not session-based should be capable of being switched over. I tested this feature on several commercial routers and it does work. Unfortunately, their software is proprietary, however, from various conversations and testing, I found that they are re-binding the sockets on failover.
As of your updated post, the problem is that changing the routing info is not going to change the source address of your ping, it will just force it out the second interface. This answer contains some relevant info.
You'll need to change the ping program. You can use a socket-per-interface approach and somehow inform the program when to fail over. Or you will have to close the socket and then bind to the second interface.
You can get the interface info required a couple of ways including calling ioctl() with the SIOCGIFCONF option and looping through the returned structures to get the interface address info.
I do't think that's quite a well-defined operation. the physical interfaces have different MAC addresses, so unless you have a routing layer mapping them (NAT or the like) then they're going to have different IP addresses.
Ports are identified by a triple of <IP addr, Port number, protocol> so if your IP address changes the port is going to change.
What are you really trying to do here?
I'm not at all sure what you're trying to accomplish, but I have a guess... Are you trying to do some kind of failover? If so, then there are indeed ways to accomplish that, but why not do it in the OS instead of the application?
On one end you can use CARP, and on the other you can use interface trunking/bonding (terminology varies) in failover mode.