大家好,我用TcpListener类创建了一个对象进行本机10000端口监听,但考虑安全性,肯定不希望外界任何人都可以连接。可能有人会说,别人不知道端口号?当我感觉端口可以扫描的吧(网上经常看到说扫描端口的,膜拜中)。
那怎么办呢?我看QQ登陆都需要用户名和密码,那么是不是这样一个原理。我客户端先CONNECT远端服务器,然后把用户名和密码发过去,服务器端验证是否正确,然后才运行通信呢?
那怎么办呢?我看QQ登陆都需要用户名和密码,那么是不是这样一个原理。我客户端先CONNECT远端服务器,然后把用户名和密码发过去,服务器端验证是否正确,然后才运行通信呢?
过滤?这个概念不是很清楚,怎么过滤?SOCKET类中有提供方法进行过滤操作的吗?
也有人说通过我上面说的方法,但SOCKET类中具体哪个方法或多个方法可以实现呢?我仔细看了MSDN,但好像没找到,能说的具体点吗?
没有底层的方法可以自动实现这个,而且就是按照这些方法去做了,也不能阻止对方不停的connect。
另外通过防火墙方案,我有点疑问?因为客户端IP是未知的,防火墙只能针对某IP进行阻止吧!是否行不通?防火墙可以检测出恶意连接,然后禁止连接吗?
DDOS攻击或者是其它的攻击 对于防御方来说总是被动的`不管你用什么方式来防着都不太管用
就像熊猫烧香一样`谁知道明天会出什么样的病毒或者攻击方式 再者说微软的"零日漏洞" 都没有办法
提前预料到`建议 在建立连接请求的时候加上一个暗号之类的东西` 客户端发一个标识性的东西,服务器接到以后解析`
合法的才接入`如果暗号不对就算你IP跟端口号一样也不让你连`直接给你喀嚓掉~ 不知道这样行不行~
现在我在干这样的事都是这样做`
服务器端:
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;namespace ConsoleApplication2
{
// State object for reading client data asynchronously
public class StateObject
{
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 1024;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
} public class AsynchronousSocketListener
{
// Thread signal.
//通知一个或多个正在等待的线程已发生事件ManualResetEvent
public static ManualResetEvent allDone = new ManualResetEvent(false); public AsynchronousSocketListener()
{
} public static void StartListening()
{
// Data buffer for incoming data.
byte[] bytes = new Byte[1024]; IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"),20000); // Create a TCP/IP socket.
Socket listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp); try
{
listener.Bind(localEndPoint);
listener.Listen(2); while (true)
{
// Set the event to nonsignaled state.
allDone.Reset(); //将事件状态设置为非终止状态,导致线程阻止。 // Start an asynchronous socket to listen for connections.
Console.WriteLine("Waiting for a connection...");
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener); // Wait until a connection is made before continuing.
allDone.WaitOne();//阻止当前线程,直到当前 WaitHandle 收到信号。
} }
catch (Exception e)
{
Console.WriteLine(e.ToString());
} Console.WriteLine("\nPress ENTER to continue...");
Console.Read(); } public static void AcceptCallback(IAsyncResult ar)
{ allDone.Set();//将事件状态设置为终止状态,允许一个或多个等待线程继续。 Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar); // Create the state object.
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
} public static void ReadCallback(IAsyncResult ar)
{
String content = String.Empty; StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.workSocket; int bytesRead = handler.EndReceive(ar); if (bytesRead > 0)
{
string sg = Encoding.ASCII.GetString(state.buffer);
if (sg.Contains("That"))
{
//验证为合法
}
else if (sg.Contains("This"))
{
//验证为非法
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
else
{
Console.WriteLine(sg); }
}
} public static int Main(String[] args)
{
StartListening();
return 0;
}
}
}
客户端1:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;namespace client
{
public partial class Form1 : Form
{
static IPEndPoint localip = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 10001);
TcpClient client = new TcpClient(localip); public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
client.BeginConnect(IPAddress.Parse("127.0.0.1"),20000, new AsyncCallback(ConnectCallback), client);
}
public static void ConnectCallback(IAsyncResult ar)
{
TcpClient s = (TcpClient)ar.AsyncState;
s.EndConnect(ar);
StateObject so2 = new StateObject();
so2.workSocket = s;
byte[] buff = Encoding.ASCII.GetBytes("This");
s.Client.BeginSend(buff, 0, buff.Length, 0,
new AsyncCallback(Send_Callback), so2);
} public static void Send_Callback(IAsyncResult ar)
{
StateObject so = (StateObject)ar.AsyncState;
TcpClient s = so.workSocket; int send = s.Client.EndSend(ar); } private void button2_Click(object sender, EventArgs e)
{
} public class StateObject
{
public TcpClient workSocket = null;
public const int BUFFER_SIZE = 1024;
public byte[] buffer = new byte[BUFFER_SIZE];
public StringBuilder sb = new StringBuilder();
} private void button2_Click_1(object sender, EventArgs e)
{
byte[] buff = Encoding.ASCII.GetBytes("asd");
client.Client.Send(buff);
}
}
}
客户端2:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;namespace client
{
public partial class Form1 : Form
{
static IPEndPoint localip = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 10000);
TcpClient client = new TcpClient(localip); public Form1()
{
InitializeComponent();
}
public static void ConnectCallback(IAsyncResult ar)
{
TcpClient s = (TcpClient)ar.AsyncState;
s.EndConnect(ar);
StateObject so2 = new StateObject();
so2.workSocket = s;
byte[] buff = Encoding.ASCII.GetBytes("This");
s.Client.BeginSend(buff, 0, buff.Length, 0,
new AsyncCallback(Send_Callback), so2);
} public static void Send_Callback(IAsyncResult ar)
{
StateObject so = (StateObject)ar.AsyncState;
TcpClient s = so.workSocket; int send = s.Client.EndSend(ar); } private void button2_Click(object sender, EventArgs e)
{
//TcpClient client = new TcpClient(IPAddress.Parse("127.0.0.1"), 10001);
client.BeginConnect(IPAddress.Parse("127.0.0.1"), 20000, new AsyncCallback(ConnectCallback), client);
}
public class StateObject
{
public TcpClient workSocket = null;
public const int BUFFER_SIZE = 1024;
public byte[] buffer = new byte[BUFFER_SIZE];
public StringBuilder sb = new StringBuilder();
} private void button1_Click(object sender, EventArgs e)
{
byte[] buff = System.Text.Encoding.Default.GetBytes("asd");
client.Client.Send(buff);
} }
}
本来想让客户端1(非法用户)CONNECT后,通过服务器验证(“THIS”),关闭掉SOCKET,让服务器不与它进行通信;BUTTON2_CLICK事件用来确认是否断开。
让客户端2(合法用户)CONNECT服务器后,可通过BUTTON2_CLICK事件发信息给服务器;
但好像关闭掉SOCKET后,连合法用户都一起断开连接了!请大家看看
实际上现在验证这个问题对你来说是个遥远的问题,这个问题应该在已经建立比较稳定可靠的socket通信的基础上,再去进一步加固其安全性。
但还有一个小问题:假如是合法用户偶然输错密码了,验证错误了,想再连一次,却始终报错,而且错误不一样:点击第一次时出现“在一个已经连接的套接字上做了一个连接请求”;点击第二次时出现“无法访问已释放的对象。”
服务器端程序:
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;namespace ConsoleApplication2
{
// State object for reading client data asynchronously
public class StateObject
{
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 1024;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
} public class AsynchronousSocketListener
{
// Thread signal.
//通知一个或多个正在等待的线程已发生事件ManualResetEvent
public static ManualResetEvent allDone = new ManualResetEvent(false); public AsynchronousSocketListener()
{
} public static void StartListening()
{
// Data buffer for incoming data.
byte[] bytes = new Byte[1024];
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"),2230);
Socket listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
try
{
listener.Bind(localEndPoint);
listener.Listen(500); while (true)
{
// Set the event to nonsignaled state.
allDone.Reset(); //将事件状态设置为非终止状态,导致线程阻止。 Console.WriteLine("Waiting for a connection...");
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener); allDone.WaitOne();//阻止当前线程,直到当前 WaitHandle 收到信号。
} }
catch (Exception e)
{
Console.WriteLine(e.ToString());
} Console.WriteLine("\nPress ENTER to continue...");
Console.Read(); } public static void AcceptCallback(IAsyncResult ar)
{
allDone.Set();//将事件状态设置为终止状态,允许一个或多个等待线程继续。
Socket listener = (Socket)ar.AsyncState; //获取用户定义的对象,它限定或包含关于异步操作的信息。
Socket handler = listener.EndAccept(ar); // Create the state object.
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
} public static void ReadCallback(IAsyncResult ar)
{
String content = String.Empty; // Retrieve the state object and the handler socket
// from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.workSocket; // Read data from the client socket.
int bytesRead = handler.EndReceive(ar); if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
string aa = System.Text.Encoding.Default.GetString(state.buffer, 0, bytesRead);
if (aa.Contains("This"))
{
Console.WriteLine(aa);
handler.Shutdown(SocketShutdown.Both);
//handler.Disconnect(true);
handler.Close();
try
{
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
//Send(handler, content);
}
else if (aa.Contains("That"))
{
// Not all data received. Get more.
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
Console.WriteLine(aa);
}
else
{
Console.WriteLine(aa);
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
}
} public static int Main(String[] args)
{
StartListening();
return 0;
}
}
}
验证错误客户端程序:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;namespace clientform
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
} public AsynchronousClient client_soc = new AsynchronousClient();
private void button1_Click(object sender, EventArgs e)
{
try
{
client_soc.StartClient();
}
catch (Exception ee)
{
textBox1.Text = ee.ToString();
//client_soc.client.Disconnect(true);
client_soc.client.Close();
//client_soc.client.
}
} public class StateObject
{
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 256;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
} public class AsynchronousClient
{
// The port number for the remote device.
private const int port = 2230;//2230 // ManualResetEvent instances signal completion.
private static ManualResetEvent connectDone =
new ManualResetEvent(false);
private static ManualResetEvent sendDone =
new ManualResetEvent(false);
private static ManualResetEvent receiveDone =
new ManualResetEvent(false); // The response from the remote device.
private static String response = String.Empty; public Socket client = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp); public void StartClient()
{
IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse("127.0.0.1"), port);
client.BeginConnect(remoteEP,
new AsyncCallback(ConnectCallback), client);
connectDone.WaitOne(); // Send test data to the remote device.
Send(client, "This");
sendDone.WaitOne();
Console.WriteLine("Response received : {0}", response);
} private static void ConnectCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket client2 = (Socket)ar.AsyncState; // Complete the connection.
client2.EndConnect(ar); Console.WriteLine("Socket connected to {0}",
client2.RemoteEndPoint.ToString()); // Signal that the connection has been made.
connectDone.Set();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
} public void Send(Socket client2, String data)
{
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data); // Begin sending the data to the remote device.
client2.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), client2);
} private static void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket client2 = (Socket)ar.AsyncState; // Complete sending the data to the remote device.
int bytesSent = client2.EndSend(ar);
//("Sent {0} bytes to server.", bytesSent); // Signal that all bytes have been sent.
sendDone.Set();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
}
}
你这个代码中捕获到的的第一个错误是因为socket未释放,第二个错误是因为socket释放了,看一下button的点击事件就可以知道原因。
{
try
{
// Create the state object.
StateObject state = new StateObject();
state.workSocket = client2; // Begin receiving the data from the remote device.
client2.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
} private static void ReceiveCallback(IAsyncResult ar)
{
try
{
// Retrieve the state object and the client socket
// from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
Socket client2 = state.workSocket; // Read data from the remote device.
int bytesRead = client2.EndReceive(ar); if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
//state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
string aa = System.Text.Encoding.Default.GetString(state.buffer, 0, bytesRead);
if (aa.Equals("asd"))
{
client2.Close();
}
else
{
// Get the rest of the data.
client2.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
}
else
{
// All the data has arrived; put it in response.
if (state.sb.Length > 1)
{
response = state.sb.ToString();
}
// Signal that all bytes have been received.
receiveDone.Set();
client2.Close(); }
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private void button1_Click(object sender, EventArgs e)
{
//AsynchronousClient client_soc = new AsynchronousClient();
client_soc = new AsynchronousClient();
try
{
client_soc.StartClient();
}
catch (Exception ee)
{
textBox1.Text = ee.ToString();
//client_soc.client.Disconnect(true);
client_soc.client.Close();
//client_soc.client.
}
}
但这里判断是否断开的方式是在客户端的ReceiveCallback函数中判断收到字节是否为0,有没有除断开连接时可能收到0字节外,还有没其他情况也会受到0字节呢?这样是否可能导致误将客户端SOCKET关闭呢!?private static void ReceiveCallback(IAsyncResult ar)
{
try
{
// Retrieve the state object and the client socket
// from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
Socket client2 = state.workSocket; // Read data from the remote device.
int bytesRead = client2.EndReceive(ar); if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
//state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
string aa = System.Text.Encoding.Default.GetString(state.buffer, 0, bytesRead);
if (aa.Equals("asd"))
{
client2.Close();
}
else
{
// Get the rest of the data.
client2.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
}
else
{
// All the data has arrived; put it in response.
if (state.sb.Length > 1)
{
response = state.sb.ToString();
}
// Signal that all bytes have been received.
receiveDone.Set();
client2.Close();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}