安全连接
确保网络传输安全
一旦在线游戏达到了一定的流行程度,人们就开始尝试作弊。那么你就需要在游戏层和网络层考虑这个这个作弊或欺骗问题。RakNet通过提供安全连接来处理这些问题,当然你也可以不使用这个机制。
RakNet提供了使用256位传输层安全的数据安全解决方案。每一个域服务器连接都拥有一个256位的椭圆曲线密钥协议实现前向安全保护。
Cookies:在握手中使用无状态的cookie,类似于SYN cookies,这使得远端IP地址欺骗这种作弊手段很难实现。
Efficient:最近两年发布,并且改进过的现代技术用于提供安全,没有任何的效率代价。
Forward secrecy:使用Tunnel Key Agreement“Tabby”协议。如果服务器在未来的某时间点被攻破,先前交换的数据不会被解密。
Protection:每一条消息都进行加密,使用消息授权码(MAC)和唯一标识符进行打戳处理,保护隐私数据,防止重放攻击。
如果服务器密钥是提前获知的,对于动态攻击(man-in-the-middle)就会免疫。
使用256位的椭圆曲线加密算法。
Elliptic Curve:在有限域Fp,p=2^n –c, c 小的曲线形状:
a’ * x ^2 + y ^ 2 = 1 + d’ * x ^ 2 *y ^ 2 , a’ = -1(在Fp平方)d’(在Fp不平方) —> 更早的曲线 = q*cofactor h, 生成点的更早值 = q
曲线满足MOV条件,不是一个类似点,使用Extended Twisted Edwards组规律实现操作。
安全连接会给每一个数据包增加11字节的数据,需要花费相应的时间计算,因此你可能希望可控地在发布的游戏中使用。
使用:
1. 增加#define LIBCAT_SECURITY 1 到 “NativeFeatureIncludesOverrides.h”。重新编译所有的文件。
2. 包含“Source/SecureHandshake.h”头文件,不要包含任何Source/cat中的文件。
3. 提前生成公有密钥和私有密钥。
cat::EasyHandshake::Initialize()
cat::EasyHandshake handshake;
char public_key[cat::EasyHandshake::PUBLIC_KEY_BYTES];
char private_key[cat::EasyHandshake::PRIVATE_KEY_BYTES];
handshake.GenerateServerKey(public_key, private_key);
4. 将公有密钥和私有密钥写入磁盘
fwrite(private_key, sizeof(private_key), 1, fp);
fwrite(public_key, sizeof(public_key), 1, fp);
5. 服务器会加载公有密钥和私有密钥,将它传递给RakPeerInterface::InitializeSecurity()方法,不要发布私有密钥,这个必须要保持保密状态。
6. 客户端应该加载公有密钥。公有密钥应该使用客户端应用程序分发,或者从安全位置下载。将公有密钥传递给RakPeerInterface::Connect()方法。
7. 按照普通的方法将客户端连接到服务器即可。
可能的错误,在packet->data[0]中返回:
ID_REMOTE_SYSTEM_REQUIRES_PUBLIC_KEY: 你没有将公有密钥传递给RakPeerInterface::Connect()。
ID_OUR_SYSTEM_REQUIRES_SECURITY: 给RakPeerInterface::Connect()传递了公有密钥,但是在服务器上并没有调用InitializeSecurity()方法
ID_PUBLIC_KEY_MISMATCH: 客户端的公有密钥与服务器上的公有密钥不匹配。
公有密钥传输:
在试着连接到远端系统时,提前生成一个公有密钥。原因是公有密钥用于表示远端系统,这样你知道回复你的系统是你真正想要连接的系统。攻击者或许知道公有密钥,但是他们不知道私有密钥(这个你是要保密的),这样他们就不能与你建立连接。
对于端到端系统,你应该运行一个专用的服务器,这个服务器必须安全。仅仅给那些服务器预先知道的客户端分发公有密钥。连接到服务器,上传对等段的公有密钥到数据库中。然后等待到来的连接。相应地,当对等端想要连接时,连接到服务器,下载这个对等端的公有密钥,使用这个公有密钥进行连接。
你可以从dx.net(http://www.dx.net/raknet_dx.php)上租用一个打折的专用服务器。
可选的解决方案:
1. 你可以使用PHPDirectoryServer来传递公有密钥。尽管不太安全,但是它仅仅需要一个PHP的webhost(典型的站点一个月仅需要$5 -$10),并且它相对来说比选择2更加安全。
2. 在RakPeer::Connect中,给acceptAnyPublicKey传递TRUE值以使用publicKey参数。这个与RakNet 第三版类似,在第三版中你仅仅需要给每一个InitialzeSecurity参数传递0。在这种情况下,不需要提前传递公有密钥。
参考在Samples\Encryption中的例子。