TCP send a packet with External IP Source? - c#

i will creat a valid TCP Packet (3 way handshake) to request on my server (real server online not vmware localhost)
My PC IP ADDRESS: 192.168.1.4
My ONLINE IP ADDRESS: 177.9.9.9
My Server IP ADDRESS: 113.x.x.x
I send a TCP Packet from my PC (177.9.9.9) to server (113.x.x.x) and success!
I can see this request showing in Wireshrak very clear with source IP is 177.9.9.9 and Destination ip is 113.x.x.x
i will write packet in C# with PCAP.NET and here is my ipV4Layer code!
IpV4Layer ipV4Layer =
new IpV4Layer
{
Source = new IpV4Address("192.168.1.4"), // My lan IP address
CurrentDestination = new IpV4Address("113.x.x.x"), // Server IP ADDRESS
HeaderChecksum = null, // Will be filled automatically.
Identification = 28104,
Options = IpV4Options.None,
Protocol = null, // Will be filled automatically.
Ttl = 128,
TypeOfService = 0,
};
NOW i want to ask, how to change 177.9.9.9 to another IP address? Not Proxy, Not socks, NOT VPN! I want to change my online IP to any IP ADDRESS, i just want to send a TCP SYN request like this and don't need server response any data, just send it with any IP address, how can do that or this way is Impossible?
Thanks for help!

If you really want to do some sort of load balancing then, go google the concept and research the viable options.
Here are some examples:
DNS based
Router/firewall/nat
Servicebus with queues, for a high level solution

Related

Problem in running Open.NAT library for port forwarding

I am trying to use a library (Open.NAT) for port forwarding the problem is that i am getting an ip address that is not actually my external ip address and neither my port is getting forwarded
Here my External ip Address by this Library
My Actual Ip Address
I treid to 'ping' that external ip address on my pc and that works completely fine but when i do the same with any other pc (which is not connected on my network ) it doesn't respond
var discoverer = new NatDiscoverer();
var cts = new CancellationTokenSource(10000);
var device = await discoverer.DiscoverDeviceAsync(PortMapper.Upnp, cts);
var ip = await device.GetExternalIPAsync();
await device.CreatePortMapAsync(new Mapping(Protocol.Tcp, 1600, 1700, "The mapping name"));
Console.WriteLine("The external IP Address is: {0} ", ip);
why this library is providing me wrong ip address & my port is not getting forwarded ?

How to force traffic on specific network adapter

I'm developing a console app to act as a client for my web-api, such as google drive, and sky drive and etc... And I ran into a edge case: my pc has 2 connections: a Ethernet and a wifi.
The Ethernet is behind a proxy and the wifi is open.
The problem here is that the ethernet is behind a proxy, that blocks the public address for my alpha tests (in windows azure).
Since windows seems to always believe only in the ethernet, which is frustrating because if it would only try the wifi, it would work... I was wondering what can i do to force to open the socket using my second network adapter (wifi).
Combining Shtééf's anwser to How does a socket know which network interface controller to use? and the MSDN Socket reference gives the following:
Suppose the PC has two interfaces:
Wifi: 192.168.22.37
Ethernet: 192.168.1.83
Open a socket as follows:
first, use Socket.Bind(EndPoint) to select the local network interface to use;
then, use Socket.Connect(EndPoint) to connect to the remote service.
`
using System.Net.Sockets;
using System.Net;
void Main()
{
Socket clientSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
int anyPort = 0;
EndPoint localWifiEP = new IPEndPoint(new IPAddress(new byte[] { 192, 168, 22, 37 }), anyPort);
EndPoint localEthernetEP = new IPEndPoint(new IPAddress(new byte[] { 192, 168, 1, 82 }), anyPort);
clientSock.Bind(localWifiEP);
// Edit endpoint to connect to an other web-api
// EndPoint webApiServiceEP = new DnsEndPoint("www.myAwsomeWebApi.org", port: 80);
EndPoint webApiServiceEP = new DnsEndPoint("www.google.com", port: 80);
clientSock.Connect(webApiServiceEP);
clientSock.Close();
}
NOTE: Using a Socket like this is somewhat low level. I could not find how to easily use Sockets —bound to a local endpoint— with higher level facilities such as HttpClient or the WCF NetHttpBinding.
For the latter you could look at How to use socket based client with WCF (net.tcp) service? for pointers how to implement your own transport.
You will need to bind the outbound socket connection to the correct network interface, see this SO post:
How does a socket know which network interface controller to use?

Connecting peers in Lidgren from a server

I would like to set up a P2P matchmaking server. The situation is as follows:
I have 2+ peers behind NAT'd router(s).
I have a server behind a port-forwarded router on a static IP.
The server's job is to register the contact information of each peer, and send it any other peer when requested.
A peer could then query the server for a list of others, and directly connect to them.
Presently, peers can connect to the server, register their addresses, and query it for other peers' addresses. My issue is introducing the peers to each other.
I am presently getting the internal and external IP addresses of each peer like so. It is heavily based around the Master Server Sample that ships with Lidgren; however, that merely connects users to client/server sessions, while I require peer to peer.
//client code; getting our internal IP and sending it to the server
NetOutgoingMessage om = server_client.CreateMessage(); //create message on the server's connection
... //header
IPAddress mask;
var endpoint = new IPEndPoint(NetUtility.GetMyAddress(out mask), peer_client.Port); //gets the internal IP address
... //write message data and send to server
When the server gets a request, or when a peer is registered to the server, it gets that peer's external IP from the connection message. We then have access to both IPs from both peers when handling a request:
//server code, handling the peer request message:
...
string key = msg.ReadString();
Output("Requesting peer: " + key);
IPEndPoint requester_internal = msg.ReadIPEndPoint();
IPEndPoint requester_external = msg.SenderEndPoint;
//attempt to find requested user
User u = null;
if (Users.TryGetValue(id, out u))
{
IPEndPoint target_internal = u.IPInternal;
IPEndPoint target_external = u.IPExternal;
...
//send the requested IPs to the sender, and the sender's IPs to the target.
}
Now, the issue is how to connect the peers to each other using this information (or, whatever other information is required to make the connection), since the other infrastructure is already functional.
My first attempt was using the built-in Introduce method:
//server code, continuing from the above
//instead of directly sending IPs to users, introduce them ourselves
s_server.Introduce(target_internal, target_external, requester_internal, requester_external, key);
This seemed to work to some degree, but it connected to the server connection on each client instead of the peer connection, and only succeeded on the sender.
Attempting to manually connect with the sent IPs resulted in endless "attempting to connect" messages:
//peer code; handling 'other peer data received' msg
IPEndPoint peer_internal = msg.ReadIPEndPoint();
IPEndPoint peer_external = msg.ReadIPEndPoint();
Output("SERVER: Recieved peer IP. Attempting to connect to:\n" + peer_internal.ToString() + "\n" + peer_external.ToString());
NetOutgoingMessage om = peer_client.CreateMessage();
om.Write((Int32)3); //unique header for debugging purposes
peer_client.Connect(peer_external, om); //tried both internal and external, no dice
Lastly, a sample case of the IPs that I'm seeing, as dumped from the server:
P1 Internal: 169.xxx.xxx.xxx:14243 //local subnet address, using the proper port
P1 External: xxx.xxx.xxx.xxx:62105 //IP address of the system, matching that from any IP testing site, but using a seemingly random port
P2 Internal: 169.xxx.xxx.xxx:14243 //same as above for the second peer
P2 External: xxx.xxx.xxx.xxx:62106
I believe that the issue is that the peer connection's external port is randomly created somewhere along the line, instead of using that which I specify when creating it. As such, it can't be forwarded in advance. I would be happy with users being required to forward a specific port, as many P2P games work this way.
In other words, I seem to have everything that I need in order to get NAT punching working properly, but I lack the knowledge of Lidgren to make it happen.
Finally, here is how I set up my peer_client:
//peer code: initialize the connection to any other peers we may connect to later
NetPeerConfiguration pconfig = new NetPeerConfiguration(appidstr_client);
pconfig.Port = 14243; //properly forwarded in router
pconfig.EnableMessageType(NetIncomingMessageType.DiscoveryRequest);
pconfig.SetMessageTypeEnabled(NetIncomingMessageType.UnconnectedData, true);
pconfig.AcceptIncomingConnections = true;
peer_client = new NetPeer(pconfig);
peer_client.Start();
Did you enable introduction messages using "config.EnableMessageType(NetIncomingMessageType.NatIntroductionSuccess);"?
Is "14243" a typo? In the sample the master server listens on 14343 and the clients listen on 14242.
"This seemed to work to some degree, but it connected to the server connection on each client instead of the peer connection, and only succeeded on the sender."
I don't understand what this means. If you're using the NetPeer class there's no specific "server connection"?
Remember IPEndPoint includes the port number, in case you're storing it away somewhere you might want to set it to the port you're trying to punch open.

get unused IP address

I need to get an available IP from the DHCP. I tried to get any ip address and start to ping the next until I reach one that doesn't respond.
public static IPAddress FindNextFree(this IPAddress address)
{
IPAddress workingAddress = address;
Ping pingSender = new Ping();
while (true)
{
byte[] localBytes = workingAddress.GetAddressBytes();
localBytes[3]++;
if (localBytes[3] > 254)
localBytes[3] = 1;
workingAddress = new IPAddress(localBytes);
if (workingAddress.Equals(address))
throw new TimeoutException("Could not find free IP address");
PingReply reply = pingSender.Send(workingAddress, 1000);
if (reply.Status != IPStatus.Success)
{
return workingAddress;
}
}
}
However, sometimes the DHCP reserves special address for some computers, so I need to get an available ip address from the dhcp.
How can I implement that in C#?
That is not the right way you are using it ,
you should request the DHCP server a new ip and then accept it ,
read about communicating with DHCP Server here
http://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol
A client application cannot make a request to the DHCP server for all available addresses.
A DHCP server can only process the following messages from a client:
DHCPDISCOVER
DHCPREQUEST
DHCPDECLINE
DHCPRELEASE
DHCPINFORM
Please see RFC 2131 - Dynamic Host Configuration Protocolfor additional information.
If you are running Windows DHCP server and you have access to the box, you can use Windows PowerShell Scripting to query the DHCP database.
Excerpt from Weekend Scripter: Parsing the DHCP Database? No Way!
Summary: Microsoft Scripting Guy, Ed Wilson, talks about a Windows PowerShell function from the DHCPServer module that permits parsing the DHCP database.
I found this app that solve the problem
http://www.centrel-solutions.com/support/tools.aspx?feature=dhcpapi

Get external IP address over remoting in C#

I need to find out the external IP of the computer a C# application is running on.
In the application I have a connection (via .NET remoting) to a server. Is there a good way to get the address of the client on the server side?
(I have edited the question, to be a little more clear. I'm apologize to all kind people who did their best to respond to the question, when I perhaps was a little too vague)
Solution:
I found a way that worked great for me. By implementing a custom IServerChannelSinkProvider and IServerChannelSink where I have access to CommonTransportKeys.IPAddress, it's easy to add the client ip on the CallContext.
public ServerProcessing ProcessMessage(IServerChannelSinkStack sinkStack,
IMessage requestmessage, ITransportHeaders requestHeaders,
System.IO.Stream requestStream, out IMessage responseMessage,
out ITransportHeaders responseHeaders, out System.IO.Stream responseStream)
{
try
{
// Get the IP address and add it to the call context.
IPAddress ipAddr = (IPAddress)requestHeaders[CommonTransportKeys.IPAddress];
CallContext.SetData("ClientIP", ipAddr);
}
catch (Exception)
{
}
sinkStack.Push(this, null);
ServerProcessing srvProc = _NextSink.ProcessMessage(sinkStack, requestmessage, requestHeaders,
requestStream, out responseMessage, out responseHeaders, out responseStream);
return srvProc;
}
And then later (when I get a request from a client) just get the IP from the CallContext like this.
public string GetClientIP()
{
// Get the client IP from the call context.
object data = CallContext.GetData("ClientIP");
// If the data is null or not a string, then return an empty string.
if (data == null || !(data is IPAddress))
return string.Empty;
// Return the data as a string.
return ((IPAddress)data).ToString();
}
I can now send the IP back to the client.
This is one of those questions where you have to look deeper and maybe rethink the original problem; in this case, "Why do you need an external IP address?"
The issue is that the computer may not have an external IP address. For example, my laptop has an internal IP address (192.168.x.y) assigned by the router. The router itself has an internal IP address, but its "external" IP address is also internal. It's only used to communicate with the DSL modem, which actually has the external, internet-facing IP address.
So the real question becomes, "How do I get the Internet-facing IP address of a device 2 hops away?" And the answer is generally, you don't; at least not without using a service such as whatismyip.com that you have already dismissed, or doing a really massive hack involving hardcoding the DSL modem password into your application and querying the DSL modem and screen-scraping the admin page (and God help you if the modem is ever replaced).
EDIT: Now to apply this towards the refactored question, "How do I get the IP address of my client from a server .NET component?" Like whatismyip.com, the best the server will be able to do is give you the IP address of your internet-facing device, which is unlikely to be the actual IP address of the computer running the application. Going back to my laptop, if my Internet-facing IP was 75.75.75.75 and the LAN IP was 192.168.0.112, the server would only be able to see the 75.75.75.75 IP address. That will get it as far as my DSL modem. If your server wanted to make a separate connection back to my laptop, I would first need to configure the DSL modem and any routers inbetween it and my laptop to recognize incoming connections from your server and route them appropriately. There's a few ways to do this, but it's outside the scope of this topic.
If you are in fact trying to make a connection out from the server back to the client, rethink your design because you are delving into WTF territory (or at least, making your application that much harder to deploy).
Dns.GetHostEntry(Dns.GetHostName()); will return an array of IP addresses. The first one should be the external IP, the rest will be the ones behind NAT.
So:
IPHostEntry IPHost = Dns.GetHostEntry(Dns.GetHostName());
string externalIP = IPHost.AddressList[0].ToString();
EDIT:
There are reports that this does not work for some people. It does for me, but perhaps depending on your network configuration, it may not work.
I found a way that worked great for me. By implementing a custom IServerChannelSinkProvider and IServerChannelSink where I have access to CommonTransportKeys.IPAddress, it's easy to add the client ip on the CallContext.
public ServerProcessing ProcessMessage(IServerChannelSinkStack sinkStack,
IMessage requestmessage, ITransportHeaders requestHeaders,
System.IO.Stream requestStream, out IMessage responseMessage,
out ITransportHeaders responseHeaders, out System.IO.Stream responseStream)
{
try
{
// Get the IP address and add it to the call context.
IPAddress ipAddr = (IPAddress)requestHeaders[CommonTransportKeys.IPAddress];
CallContext.SetData("ClientIP", ipAddr);
}
catch (Exception)
{
}
sinkStack.Push(this, null);
ServerProcessing srvProc = _NextSink.ProcessMessage(sinkStack, requestmessage, requestHeaders,
requestStream, out responseMessage, out responseHeaders, out responseStream);
return srvProc;
}
And then later (when I get a request from a client) just get the IP from the CallContext like this.
public string GetClientIP()
{
// Get the client IP from the call context.
object data = CallContext.GetData("ClientIP");
// If the data is null or not a string, then return an empty string.
if (data == null || !(data is IPAddress))
return string.Empty;
// Return the data as a string.
return ((IPAddress)data).ToString();
}
I can now send the IP back to the client.
Better to just use http://www.whatismyip.com/automation/n09230945.asp it only outputs the IP just for the automated lookups.If you want something that does not rely on someone else put up your own page http://www.unkwndesign.com/ip.php is just a quick script:
<?php
echo 'Your Public IP is: ' . $_SERVER['REMOTE_ADDR'];
?>
The only downside here is that it will only retrieve the external IP of the interface that was used to create the request.
Jonathan Holland's answer is fundamentally correct, but it's worth adding that the API calls behind Dns.GetHostByName are fairly time consuming and it's a good idea to cache the results so that the code only has to be called once.
The main issue is the public IP address is not necessarily correlated to the local computer running the application. It is translated from the internal network through the firewall. To truly obtain the public IP without interrogating the local network is to make a request to an internet page and return the result. If you do not want to use a publicly available WhatIsMyIP.com type site you can easily create one and host it yourself - preferably as a webservice so you can make a simple soap compliant call to it from within your application. You wouldn't necessarily do a screen capture as much as a behind the scenes post and read the response.
If you just want the IP that's bound to the adapter, you can use WMI and the Win32_NetworkAdapterConfiguration class.
http://msdn.microsoft.com/en-us/library/aa394217(VS.85).aspx
Patrik's solution works for me!
I made one important change. In process message I set the CallContext using this code:
// try to set the call context
LogicalCallContext lcc = (LogicalCallContext)requestMessage.Properties["__CallContext"];
if (lcc != null)
{
lcc.SetData("ClientIP", ipAddr);
}
This places the ip address in the correct CallContext, so it can later be retrieved with
GetClientIP().
Well, assuming you have a System.Net.Sockets.TcpClient connected to your client, you can (on the server) use client.Client.RemoteEndPoint. This will give you a System.Net.EndPoint pointing to the client; that should contain an instance of the System.Net.IPEndPoint subclass, though I'm not sure about the conditions for that. After casting to that, you can check it's Address property to get the client's address.
In short, we have
using (System.Net.Sockets.TcpClient client = whatever) {
System.Net.EndPoint ep = client.Client.RemoteEndPoint;
System.Net.IPEndPoint ip = (System.Net.IPEndPoint)ep;
DoSomethingWith(ip.Address);
}
Good luck.
I believe theoretically you are unable to do such a thing while being behind a router (e.g. using invalid ip ranges) without using an external "help".
You can basically parse the page returned by doing a WebRequest of http://whatismyipaddress.com
http://www.dreamincode.net/forums/showtopic24692.htm
The most reliable manner of doing this is checking a site like http://checkip.dyndns.org/ or similar, because until you actually go external to your network, you cannot find your external IP. However, hardcoding such a URL is asking for eventual failure. You may wish to only perform this check if the current IP looks like an RFC1918 private address (192.168.x.x being the most familiar of these.
Failing that, you can implement your own, similar, service sitting external to the firewall, so you will at least know if it's broken.

Categories