协议加密
从2.10版开始,SmartFoxServer 2X支持连接加密,允许使用标准TLS协议保护所有通信。
在本文中,我们将讨论加密流量如何在SmartFoxServer中运行的基础知识,如何在服务器上设置X.509证书,如何测试连接以及某些特定于平台的笔记。
注意:自从2.9.x版本以来,websocket客户端已经支持SSL,在本文中,我们仅讨论SSL TCP套接字。对于websockets,请参考这篇文章。
简单来说,它是如何工作的
将完全加密的加密添加到客户端的会话中,在连接事件之后只需要一个调用。下图显示了以下过程:
密码流
首先,与服务器建立持久连接。然后调用新的InitCrypto()方法来执行加密握手。如果请求成功,客户端和服务器已正确同意将用于加密消息的私钥。
从这一点起,所有通信都受128位对称加密保护。
»在引擎盖下
SmartFox.InitCrypto()调用与嵌入式Jetty Web服务器结合使用,以通过HTTPS交换唯一且安全的令牌。通过使用已经安全的交换渠道,我们可以确保服务器在具有有效SSL证书的域上运行,以避免中间人的攻击。
SFSEvent.CRYPTO_INIT用于以表示操作成功的布尔值来表示来自服务器的响应。
一旦私有密钥被采集,其余的通信将被API透明地加密,使用AES 128位加密技术。
»服务器设置
1)启用HTTPS
要在SmartFoxServer 2.10及更高版本中激活加密,第一步是在AdminTool的ServerSettings> Web服务器下激活HTTPS。
默认HTTPS端口为8443.无论您保留此值还是自定义,请始终确保您没有阻止通信的防火墙。
另外,如果是生产服务器,则需要在SmartFoxServer中安装有效的SSL证书。
2)配置您的区域的加密设置
在AdminTool> ZoneConfigurator下选择您的工作区。在第一个标签下,您会发现:
打开使用加密标志并重新启动服务器以激活更改。
»SSL证书
SmartFoxServer 2X默认安装了一个自签名证书,可用于在本地测试您的游戏。然而,这对于生产服务器将无法正常工作。对于实时服务器,必须签署安全证书。
»本地测试
测试的最简单的方法不会导致安全问题,是在开发环境中禁用加密,并且只是测试生产服务器上真正需要的加密。一个简单的方法是通过组织您的连接代码,如下例所示:
public class BasicClientExample implements IEventListener
{
// Use this to turn Cryptography ON and OFF
private boolean useCrypto = false;
private SmartFox sfs;
public BasicClientExample()
{
sfs = new SmartFox();
sfs.addEventListener(SFSEvent.CONNECTION, evtListener);
sfs.addEventListener(SFSEvent.CRYPTO_INIT, evtListener);
sfs.addEventListener(SFSEvent.LOGIN, evtListener);
ConfigData cfg = new ConfigData();
cfg.setHost("localhost");
cfg.setZone("BasicExamples");
cfg.setDebug(false);
sfs.connect(cfg);
}
private void sendLogin()
{
sfs.send(new LoginRequest("", "", sfs.getCurrentZone()));
}
@Override
public void dispatch(BaseEvent event)
{
if (event.getType().equals(SFSEvent.CONNECTION))
{
boolean success = (Boolean) event.getArguments().get("success");
if (success)
{
if (useCrypto)
sfs.initCrypto();
else
sendLogin();
}
}
else if (event.getType().equals(SFSEvent.CRYPTO_INIT))
{
boolean success = (Boolean) event.getArguments().get("success");
if (success)
sendLogin();
else
System.err.println(">>> CRYPTO INIT FAIL: " + event.getArguments().get("errorMsg"));
}
else if (event.getType().equals(SFSEvent.LOGIN))
{
System.out.println("Logged In: " + sfs.getMySelf().getName());
}
}
}
通过使用私有布尔标志(useCrypto),我们可以使本地环境与生产的密码开关非常简单。
»使用自签名证书进行本地测试
一般来说,我们不建议使用默认的自签名证书进行本地测试。由于每个运行时(浏览器,操作系统,设备等)都不会通过授权机构签名,而是以某种方式进行投诉,并停止您的应用程序。可能有也可能没有办法强制系统使用非签名证书,但这可能是一个棘手的过程。
我们强烈推荐,而不是在本地进行加密测试,并使用常规的签名证书进行在线测试。
如果您仍然希望使用加密技术运行本地测试,那么只有在您真正了解运行时安全性的原理时,我们才建议使用它们。
对于浏览器插件环境,这相当于连接到具有无效证书的HTTPS网站。浏览器将停止导航并显示突出的警告。用户然后可以离开或覆盖警告并继续,忽略安全风险。
警报
然而,这不会显示出来,因为连接是在插件内完成的,因此错误可能会被检测到。
以下是一些有助于本地测试的技巧:
基于Web的:在使用Flash Player等基于Web的插件进行测试时,可以在测试前将安全异常添加到浏览器中来克服此问题。将浏览器指向https:// <testHost>:<portNumber>并手动覆盖异常。
基于Java:有一点额外的代码,可以使JVM忽略SSL异常。在这个StackOverflow讨论中看到这个问题的第一个答案。
基于C#:我们不知道如何规避安全错误,因此我们不建议使用自签名证书运行本地测试。而是在其中一个域上使用有效的SSL证书。
»使用正版SSL证书进行在线测试
对于生产服务器,必须提供有效的SSL证书。您可以从许多不同的提供商获取一个或使用现有的提供商,并将其导入到SmartFoxServer。
证书有几种不同的文件格式。通常你会得到2或3个文件:
证书(.pem)
私钥(.pem)
(可选)中介证书(.pem)
通过这样的在线工具,我们可以创建一个.pfx(或p12)文件,然后可以通过JDK的keytool实用程序将其导入到密钥库中。
keytool -importkeystore -srckeystore cert.pfx -srcstoretype pkcs12 -destkeystore
key-store-name.jks -deststoretype JKS
哪里:
cert.pxf是通过在线工具获取的文件
pkcs12指定.pfx / .p12文件的文件格式
key-store-name.jks是我们最终密钥库文件的名称
密钥库文件是我们将在SmartFoxServer 2X中部署的文件,具体步骤如下:
将密钥库复制到SFS2X / lib / jetty / etc;
编辑jetty / start.d / ssl.ini文件并配置密钥库文件名和密码。
这是ssl.ini的一个例子
#
#初始化模块ssl
#
–module = ssl
SSL密钥库配置
#定义要用于安全重定向的端口
jetty.secure.port = 8443
#设置一个演示密钥库和信任库
jetty.keystore = etc / myCertificate.jks
jetty.truststore = etc / myCertificate.jks
#设置演示密码。
#请注意,OBF密码不安全,只是防止随意观察
#见http://www.eclipse.org/jetty/documentation/current/configuring-security-secure-passwords.html
jetty.keystore.password = myPassword
jetty.keymanager.password = myPassword
jetty.truststore.password = myPassword
由于此文件包含对系统安全性至关重要的密码,因此我们建议您确保它受到足够的文件权限的保护。评论中的链接提供了有关如何掩盖密码(如果需要)的其他信息。
最后,为了验证SSL证书是否正常工作,您可以将浏览器指向https //::,并确认您的浏览器报告了一个成功的连接(例如下面的绿色锁定)。
平台具体说明
»Adobe Flash
Flash IDE将始终无法使用加密方式连接到具有自签名证书的本地SmartFoxServer。 独立的Flash Player也是一样。 在这种设置中测试的唯一方法是通过预先授权域来使用浏览器,如本文前面所述。
»团结
在Unity中,SmartFox.InitCrypto方法必须作为协同程序执行,因此使用MonoBehaviour.StartCoroutine方法。 由于在Windows Store(SDK 8.1,Phone 8.1,Universal 8.1)应用程序中不支持此功能,因此在为此平台构建时需要一个条件语句,如以下示例所示:
// Initialize encrypted connection
#if UNITY_WINRT && !UNITY_EDITOR
sfs.InitCrypto();
#else
StartCoroutine(sfs.InitCrypto());
#endif
对于Windows Store IL2CPP构建,请按照本文中所述更改上述条件编译。
Unity WebPlayer
不要在你的代码中使用Socket.PrefetchPolicy。
它强制使用IP地址而不是域名,如果您要使用SSL,那么这是必需的,因为证书(通常)绑定到域名。
相反,您可以让WebPlayer从默认TCP端口843自动获取跨域策略。为此,您需要在SFS2X AdminTool>服务器配置器中为此类端口添加一个侦听器。
对于Linux / Mac OS X用户,这需要以root身份运行服务器,因为端口843位于0-1024范围内。
在构建WebGL时,此方法不可用:改为使用WSS连接。
Unity WebGL
SmartFox.InitCrypto方法在构建WebGL时不可用:使用WSS连接(参见SmartFox(UseWebSocket useWebSocket)构造函数API文档))。
翻译自http://docs2x.smartfoxserver.com/GettingStarted/cryptography