Как читать защищенные веб-запросы и обрабатывать запросы веб-сокетов с помощью одного Java ServerSocket? - PullRequest
0 голосов
/ 28 декабря 2018

Intro

Мой код может обрабатывать все байты, отправленные на сервер, и решать, разрешать или не пропускать их, и в конечном итоге отправлять ответы.Я хотел бы использовать это для использования сервера в качестве веб-сервера, сервера веб-сокетов и tcp-сервера в одном.

Хотя мой код написан для Minecraft, я не спрашиваю об этом на форуме Minecraft, потому что отвечаю на этот вопросне требует никаких предварительных знаний о Minecraft или его кодовой базе.

Все, что вам нужно знать о Minecraft

Minecraft - это игра на Java, в которую можно играть онлайн.Когда он воспроизводится онлайн, есть сервер, который открывает ServerSocket, и у всех игроков есть свой собственный клиент, который открывает Socket, который будет связываться с ServerSocket сервера.

Любой может создать сервер Minecraft и установитьсерверные модификации на своем сервере (для тех, кто знает Minecraft, их обычно называют плагинами).Мое приложение является такой серверной модификацией.Большинство серверов Minecraft размещаются на хост-компаниях Minecraft.Владельцы серверов имеют некоторый доступ к той части хост-компьютера, которая управляет файлами сервера.

Цель

Цель моей модификации - позволитьсервер Minecraft обслуживает больше клиентов, чем просто клиентов Minecraft.Я хотел бы, чтобы этот сервер также работал в качестве веб-сервера (для запросов http и https), а также (защищенного) сервера веб-сокетов и tcp-сервера.

Почему нет нескольких серверных сокетов

Наиболее распространенным решением было бы просто создать ServerSocket для других типов серверов и назначить для них разные порты.Тем не менее, это не вариант в моем случае.Большинство хостов запрещают вам открывать другие порты или просить за это дополнительные деньги.Поэтому мне нужно сделать все это только с помощью Minecraft ServerSocket.

Чего я достиг на данный момент

До сих пор мне удалось разрешить все байты, которые отправляются насервер майнкрафт сначала проходит мой код.Мой код может выбрать, разрешать ли байты продолжать код сервера Minecraft.Он также может отправлять ответы самостоятельно, без необходимости сообщать код сервера Minecraft.

В принципе, того, что мне удалось сделать, достаточно для достижения моей цели, но я хотел бы помочь спродолжать.Ниже я объясню, что у меня есть и чего еще не достигнуто.

Первый байт, отправляемый клиентом Minecraft на сервер, всегда один и тот же, а именно 16. Это здорово, потому что позволяет легкоотличать клиентов Minecraft от веб-браузеров и tcp-клиентов.

HTTP-запросы и соединения веб-сокетов всегда начинаются с одного байта, а именно 71. HTTPS и защищенные веб-сокеты всегда начинаются с байта 22. TCP-соединения, о которых я говорилотправлены моими собственными приложениями, поэтому я могу точно выбрать, какие байты они будут отправлять, и я могу просто запрограммировать свою модификацию, чтобы ответить на это.

Мне удалось различить запросы http и соединения веб-сокетов по их свойству соединения.Http-запросы всегда отправляют «Connection: keep-alive», в то время как веб-сокеты всегда отправляют «Connection: upgrade».(Хотя некоторые браузеры делают буквы k, a и u в верхнем регистре, а другие нет.)

Обработка обычных запросов http не была очень трудной.Управлять TCP-соединениями тоже не составит труда, потому что я буду контролировать все.Но у меня есть проблемы с остальными типами соединения:

Проблемы, мне нужна помощь с

Протокол веб-сокетов довольно большой, и я бы предпочел не обрабатывать его полностью только с помощью моего кода.(Я пытался сделать это раньше, но у меня возникали проблемы с частями, которые редко использовались и, следовательно, не тестировались.) Поэтому я хотел бы использовать некоторую библиотеку, которая позволяет мне беспокоиться только о полезной нагрузке, а не обо всем протоколе.К сожалению, библиотеки веб-сокетов обычно хотят создать ServerSocket, что в моем случае невозможно. Так у кого-нибудь есть совет, что делать здесь?

Я не нашел никакой информации о том, как правильно читать запросы https. Может кто-нибудь сказать мне, где искать подробности этого протокола или предоставить хорошую ссылку? Для безопасных веб-сокетов я столкнусь с теми же проблемами, что и с «обычными» веб-сокетами после того, как узнаю, какчитать запросы.

Код

Весь мой код до сих пор можно найти на https://github.com/knokko/Multi-Purpose-Server. Самая интересная часть, вероятно, часть, где мой кодполучает возможность обработать все байты до того, как они получат код Minecraft, этот код показан ниже.

Короткие вопросы

Для тех, кто этого не сделалточно понять, что мой вопрос (вы можете видеть его как два тесно связанных вопроса):

-Как мне следует читать запросы https и защищенные рукопожатия через веб-сокет?

-Кто-нибудь знаетбиблиотека, которая может обрабатывать ввод через веб-сокет и не требует создания самого ServerSocket?

// This channel handler will be registered for every connection client that will
                    // inspect
                    // any message before it reaches the Minecraft code.
                    pipeline.addFirst("multipurpose_handler_inspector", new ChannelInboundHandlerAdapter() {

                        private boolean deactivated;

                        private ChannelListener listener;

                        @Override
                        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                        //super.channelRead will send the content to the minecraft code
                            try {
                                if (!deactivated) {
                                    ByteBuf message = (ByteBuf) msg;
                                    if (listener != null) {
                                        listener.read(ctx, message);
                                    } else {
                                        byte firstByte = message.getByte(0);

                                        // All Minecraft connections start with the byte 16
                                        if (firstByte == 16) {
                                            deactivated = true;
                                            super.channelRead(ctx, msg);
                                        }

                                        // All insecure web connections start with the byte 71
                                        else if (firstByte == 71) {
                                            byte[] data = new byte[message.readableBytes()];
                                            message.getBytes(0, data);
                                            WebHandler.Type type = WebHandler.determineConnectionType(data);
                                            if (type == WebHandler.Type.HTTP) {
                                                listener = new HTTPListener();
                                                listener.readInitial(ctx, message);
                                            } else if (type == WebHandler.Type.WEBSOCKET) {
                                                // TODO Find a nice way to handle web socket connections
                                                listener = new WebSocketListener();
                                                listener.readInitial(ctx, message);
                                            } else {
                                                deactivated = true;
                                                super.channelRead(ctx, msg);
                                            }
                                        }

                                        // All secure web connections start with the byte 22
                                        else if (firstByte == 22) {
                                            // TODO implement the secure web protocols and find a way to read this stuff
                                            // and find the difference
                                            System.out.println(
                                                    "We are dealing with a secure websocket or https connection");
                                            byte[] data = new byte[message.readableBytes()];
                                            message.getBytes(0, data);
                                            System.out.println(new String(data));
                                        }

                                        // My applications
                                        else if (firstByte == 31) {
                                            listener = new TCPListener();
                                            listener.readInitial(ctx, message);
                                        } else {
                                            System.out.println("Unknown connection type");
                                            deactivated = true;
                                            super.channelRead(ctx, msg);
                                        }
                                    }
                                } else {
                                    super.channelRead(ctx, msg);
                                }
                            } catch (Exception ex) {
                                ex.printStackTrace();
                            }
                        }
                    });

1 Ответ

0 голосов
/ 28 декабря 2018

Если вы ВСЕГДА можете идентифицировать трафик Minecraft, вам лучше всего запустить сервер apache / httpd и / или tomcat на одном компьютере и перенаправить на него весь трафик, не относящийся к Minecraft.Если вы сделаете это, то HTTPS может быть просто вопросом правильной настройки http-сервера для трафика https.

Возможно, вам придется настроить ваш код как http-прокси - фактически (только что подумал)Возможно, вы захотите выйти и поискать http-прокси с открытым исходным кодом и просто настроить его с помощью своего кода, чтобы извлечь трафик Minecraft и переслать его, прежде чем выполнять оставшуюся часть прокси.

Я бы не стал использовать HTTPвсе с нуля, это не очень сложно, но я бы назвал это нетривиальным.

О, и если ваша проблема заключается в «дифференцировании трафика Minecraft HTTPS от других подключений HTTPS через тот же порт», я не могу помочь, кромесказать, что это может быть хорошей темой для вашего вопроса:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...