【问题标题】:AS3 Verify Socket Host Connection - Resolve Host?AS3 验证套接字主机连接 - 解析主机?
【发布时间】:2014-09-03 06:03:59
【问题描述】:

我遇到了一个问题,人们通过使用他们的本地 HOST 文件来操纵我的游戏客户端套接字的连接。也就是说,我有一些类似的方法

    private var _socket : Socket;
    public function init(host : String, port : uint = 0) : Boolean {
        _socket.connect(host, port);
        return true;
    }

我希望主机始终类似于“example.game.com”,并且始终解析为某个 ip“255.255.255.255”。但是,通过使用 HOST 文件,“example.game.com”可能会解析为“127.0.0.1”,这允许第三方应用程序拦截和修改游戏数据。

它的骗子是我不能使用 DNSResolver,因为这需要 AIR,解决方案必须是纯 Actionscript。我也不能相信对某些外部 JS/PHP 脚本的请求会为我解决它,因为可以使用一些 HTTP 代理(例如 Fiddler)来修改它的结果

有没有人有任何纯 AS3 解决方案可以让我确保我的套接字连接到的主机是我想要的?

【问题讨论】:

  • 我也对这个问题投了赞成票,因为这是一个很好的问题,应该有更多的人来问。

标签: actionscript-3 sockets dns host resolve


【解决方案1】:

我可以想到两种方法。

首先,从最初的测试来看,您似乎可以查询 remoteHost 和 remotePort。即使您使用主机,它们也会返回对您有用的值。如下所示。

其次,您可以将套接字设置为 ping Flash,以便每 5 分钟左右得到响应。有 ping 请求 localAddress、localPort、remoteAddress 和 remotePort。如果它们与您收到数据时的预期不符,请终止连接。

最重要的是,每当您收到数据时,都要在服务器端进行验证。让你的服务器知道玩家在做什么,以及什么是合理的。 Mos 多人游戏(这是我假设的),有效地在服务器上“运行”自己。因此,如果用户 A 确实设法绕过了您设置的安全性并说他想击中 5000 码外的目标并造成 150 万伤害,那么服务器已经知道:

  • 他不在范围内
  • B 他不能造成那么大的伤害

在开发最终游戏时,此主题是最难管理的主题之一。虽然您可以与之抗争,并且大部分都赢了,但您永远不会阻止人们“模拟”服务器并在那里使用您的内容。但是,您应该能够阻止大多数注入到您的游戏中。

编辑:当人们开始反编译 SWF 并设法重新编译它时,您的问题才真正开始。然后,任何客户端验证都将被排除在外,因为它们将删除您已有的验证,并且您 100% 依赖于服务器端验证。这也可以通过内存编辑来实现,不过……一般来说,客户端验证只会阻止更基本的“黑客”。

package kazo 
{
    import flash.net.SharedObject;
    import flash.net.Socket;
    import flash.events.Event
    import flash.events.ProgressEvent
    import flash.events.SecurityErrorEvent
    import flash.events.IOErrorEvent
    /**
     * ...
     * @author KM
     */
    public class TestCases 
    {

        private var socket:Socket;

        private const ADDRESS_LIST:Vector.<String> = {
            '255.255.255.255',
            '255.255.255.254'
        }
        private const PORT_LIST:Vector.<String> = {
            '111',
            '112'
        }

        public function TestCases() { }

        /**
         * Start the test case
         */
        public function start():void {
            trace('Starting test case');

            socket = new Socket();

            socket.addEventListener(Event.CONNECT, onConnect);
            socket.addEventListener(ProgressEvent.SOCKET_DATA, onData);

            socket.connect('example.domain.com', port);
        }

        /**
         * 
         * @param   e
         */
        private function onConnect(e:Event):void {
            trace(socket.remoteAddress);
            trace(socket.remotePort);

            // validate before doing anything
            validateNow();
        }

        /**
         * 
         * @param   e
         */
        private function onData(e:ProgressEvent):void {
            trace(e.target);

            // validate before processing data
            validateNow();
        }

        /**
         * 
         */
        private function validateNow():void {
            var i:int = 0;
            // List of allowed ports (MUST be hardcoded)
            var portLen:int = PORT_LIST.length;
            // List of addresses (MUST be hardcoded)
            var addressLen:int = ADDRESS_LIST.length;

            var addressPass:Boolean;
            var portPass:Boolean;

            // Loop through, make sure we're valid
            for (i; i < portLen; i++) {
                PORT_LIST[i] === socket.remotePort ? portPass = true : continue;
            }

            // Loop through, make sure we're valid
            for (i = 0; i < addressLen; i++) {
                ADDRESS_LIST[i] === socket.remoteAddress ? addressPass = true : continue;
            }

            // If we're not, close off. If we are, run the course
            if (!addressPass || !portPass) {
                socket.close();
                // inform server
            }
        }

    }

}

【讨论】:

  • 你激活了我的陷阱卡!这是对任何存在类似问题的机构的非常详细且消息灵通的回应,可以使用 remoteAddress、remotePort 方法。这些方法仅在 AIR 运行时内部可用。我的问题是我无法使用这些方法,因此挑战变得越来越困难!
  • 诚然,我的默认设置是导出 AIR Captive Run time。也就是说,为什么他们只把这 4 个属性做成 AIR 的血腥地狱是我无法理解的。在这种情况下,您将真正与这个作斗争。我的建议是在连接时向客户端发送一个变量,该变量在每次登录时随机分配。然后,客户端每次向您的服务器发出请求时都必须使用此变量进行响应。在服务器端生成变量,并且只有在成功连接后才发送它(并且只有一次)。这样一来,用户就无法轻松做到这一点。
  • 基本上,在验证请求的方式上发挥创意。做到这一点,如果有人在模拟您的服务器,他们将无法获得一两个字段,而无需首先建立真正的连接。然后,为每个用户更改该变量。将其存储在数据库中,并在每次登录请求命中您时将其重置为新的。针对应该已经分配的变量验证所有服务器调用。
  • @DominicGunn 我真的很想听听你如何解决这个问题,以及我的建议是否有帮助,或者你是否走另一条路。这是一个有趣的话题。
猜你喜欢
  • 2012-06-21
  • 2020-07-15
  • 1970-01-01
  • 1970-01-01
  • 2017-11-07
  • 1970-01-01
  • 2014-03-21
  • 2010-09-14
  • 2016-07-09
相关资源
最近更新 更多