mirror of
https://git.krews.org/morningstar/nitrowebsockets-for-ms
synced 2024-11-26 08:50:51 +01:00
Merge branch 'http-headers' into dev
This commit is contained in:
commit
a7c7c92241
2
pom.xml
2
pom.xml
@ -24,7 +24,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.eu.habbo</groupId>
|
<groupId>com.eu.habbo</groupId>
|
||||||
<artifactId>Habbo</artifactId>
|
<artifactId>Habbo</artifactId>
|
||||||
<version>2.5.0</version>
|
<version>3.0.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
22
src/main/java/org/krews/plugin/nitro/Utils.java
Normal file
22
src/main/java/org/krews/plugin/nitro/Utils.java
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package org.krews.plugin.nitro;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
public class Utils {
|
||||||
|
public static String getDomainNameFromUrl(String url) throws Exception {
|
||||||
|
URI uri = new URI(url);
|
||||||
|
String domain = uri.getHost();
|
||||||
|
return domain.startsWith("www.") ? domain.substring(4) : domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isWhitelisted(String toCheck, String[] whitelist) {
|
||||||
|
for(String whitelistEntry : whitelist) {
|
||||||
|
if(whitelistEntry.startsWith("*")) {
|
||||||
|
if(toCheck.endsWith(whitelistEntry.substring(1)) || ("." + toCheck).equals(whitelistEntry.substring(1))) return true;
|
||||||
|
} else {
|
||||||
|
if(toCheck.equals(whitelistEntry)) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -6,12 +6,16 @@ import com.eu.habbo.plugin.EventHandler;
|
|||||||
import com.eu.habbo.plugin.EventListener;
|
import com.eu.habbo.plugin.EventListener;
|
||||||
import com.eu.habbo.plugin.HabboPlugin;
|
import com.eu.habbo.plugin.HabboPlugin;
|
||||||
import com.eu.habbo.plugin.events.emulator.EmulatorLoadedEvent;
|
import com.eu.habbo.plugin.events.emulator.EmulatorLoadedEvent;
|
||||||
|
import com.eu.habbo.plugin.events.users.UserGetIPAddressEvent;
|
||||||
|
import io.netty.channel.Channel;
|
||||||
|
import io.netty.util.AttributeKey;
|
||||||
import org.krews.plugin.nitro.websockets.NetworkChannelInitializer;
|
import org.krews.plugin.nitro.websockets.NetworkChannelInitializer;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
public class main extends HabboPlugin implements EventListener {
|
public class main extends HabboPlugin implements EventListener {
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(main.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(main.class);
|
||||||
|
public static final AttributeKey<String> WS_IP = AttributeKey.valueOf("WS_IP");
|
||||||
|
|
||||||
public void onEnable() throws Exception {
|
public void onEnable() throws Exception {
|
||||||
Emulator.getPluginManager().registerEvents(this, this);
|
Emulator.getPluginManager().registerEvents(this, this);
|
||||||
@ -34,6 +38,7 @@ public class main extends HabboPlugin implements EventListener {
|
|||||||
Emulator.getConfig().register("websockets.whitelist", "localhost");
|
Emulator.getConfig().register("websockets.whitelist", "localhost");
|
||||||
Emulator.getConfig().register("ws.nitro.host", "0.0.0.0");
|
Emulator.getConfig().register("ws.nitro.host", "0.0.0.0");
|
||||||
Emulator.getConfig().register("ws.nitro.port", "2096");
|
Emulator.getConfig().register("ws.nitro.port", "2096");
|
||||||
|
Emulator.getConfig().register("ws.nitro.ip.header", "");
|
||||||
|
|
||||||
NetworkChannelInitializer wsChannelHandler = new NetworkChannelInitializer();
|
NetworkChannelInitializer wsChannelHandler = new NetworkChannelInitializer();
|
||||||
Emulator.getGameServer().getServerBootstrap().childHandler(wsChannelHandler);
|
Emulator.getGameServer().getServerBootstrap().childHandler(wsChannelHandler);
|
||||||
@ -43,4 +48,15 @@ public class main extends HabboPlugin implements EventListener {
|
|||||||
LOGGER.info("OFFICIAL PLUGIN - Nitro Websockets has started!");
|
LOGGER.info("OFFICIAL PLUGIN - Nitro Websockets has started!");
|
||||||
LOGGER.info("Nitro Websockets Listening on " + (wsChannelHandler.isSSL() ? "wss://" : "ws://") + Emulator.getConfig().getValue("ws.nitro.host", "0.0.0.0") + ":" + Emulator.getConfig().getInt("ws.nitro.port", 2096));
|
LOGGER.info("Nitro Websockets Listening on " + (wsChannelHandler.isSSL() ? "wss://" : "ws://") + Emulator.getConfig().getValue("ws.nitro.host", "0.0.0.0") + ":" + Emulator.getConfig().getInt("ws.nitro.port", 2096));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onUserGetIPEvent(UserGetIPAddressEvent e) {
|
||||||
|
Channel channel = e.habbo.getClient().getChannel();
|
||||||
|
if(channel != null && channel.hasAttr(main.WS_IP)) {
|
||||||
|
String ip = channel.attr(main.WS_IP).get();
|
||||||
|
if(!ip.isEmpty()) {
|
||||||
|
e.setUpdatedIp(ip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ import io.netty.handler.logging.LoggingHandler;
|
|||||||
import io.netty.handler.ssl.SslContext;
|
import io.netty.handler.ssl.SslContext;
|
||||||
import io.netty.handler.timeout.IdleStateHandler;
|
import io.netty.handler.timeout.IdleStateHandler;
|
||||||
import org.krews.plugin.nitro.websockets.codec.WebSocketCodec;
|
import org.krews.plugin.nitro.websockets.codec.WebSocketCodec;
|
||||||
|
import org.krews.plugin.nitro.websockets.handlers.CustomHTTPHandler;
|
||||||
import org.krews.plugin.nitro.websockets.ssl.SSLCertificateLoader;
|
import org.krews.plugin.nitro.websockets.ssl.SSLCertificateLoader;
|
||||||
|
|
||||||
public class NetworkChannelInitializer extends ChannelInitializer<SocketChannel> {
|
public class NetworkChannelInitializer extends ChannelInitializer<SocketChannel> {
|
||||||
@ -37,6 +38,7 @@ public class NetworkChannelInitializer extends ChannelInitializer<SocketChannel>
|
|||||||
}
|
}
|
||||||
ch.pipeline().addLast("httpCodec", new HttpServerCodec());
|
ch.pipeline().addLast("httpCodec", new HttpServerCodec());
|
||||||
ch.pipeline().addLast("objectAggregator", new HttpObjectAggregator(65536));
|
ch.pipeline().addLast("objectAggregator", new HttpObjectAggregator(65536));
|
||||||
|
ch.pipeline().addLast("customHttpHandler", new CustomHTTPHandler());
|
||||||
ch.pipeline().addLast("protocolHandler", new WebSocketServerProtocolHandler("/", true));
|
ch.pipeline().addLast("protocolHandler", new WebSocketServerProtocolHandler("/", true));
|
||||||
ch.pipeline().addLast("websocketCodec", new WebSocketCodec());
|
ch.pipeline().addLast("websocketCodec", new WebSocketCodec());
|
||||||
|
|
||||||
|
@ -1,23 +1,14 @@
|
|||||||
package org.krews.plugin.nitro.websockets.codec;
|
package org.krews.plugin.nitro.websockets.codec;
|
||||||
|
|
||||||
import com.eu.habbo.Emulator;
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.channel.ChannelFutureListener;
|
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.handler.codec.MessageToMessageCodec;
|
import io.netty.handler.codec.MessageToMessageCodec;
|
||||||
import io.netty.handler.codec.http.websocketx.*;
|
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
|
||||||
import org.krews.plugin.nitro.main;
|
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
import java.net.URISyntaxException;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class WebSocketCodec extends MessageToMessageCodec<WebSocketFrame, ByteBuf> {
|
public class WebSocketCodec extends MessageToMessageCodec<WebSocketFrame, ByteBuf> {
|
||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketCodec.class);
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void encode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
|
protected void encode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
|
||||||
out.add(new BinaryWebSocketFrame(in).retain());
|
out.add(new BinaryWebSocketFrame(in).retain());
|
||||||
@ -27,43 +18,5 @@ public class WebSocketCodec extends MessageToMessageCodec<WebSocketFrame, ByteBu
|
|||||||
protected void decode(ChannelHandlerContext ctx, WebSocketFrame in, List<Object> out) {
|
protected void decode(ChannelHandlerContext ctx, WebSocketFrame in, List<Object> out) {
|
||||||
out.add(in.content().retain());
|
out.add(in.content().retain());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
|
|
||||||
// only allow websockets connections from the whitelist
|
|
||||||
if(evt instanceof WebSocketServerProtocolHandler.HandshakeComplete) {
|
|
||||||
WebSocketServerProtocolHandler.HandshakeComplete handshake = (WebSocketServerProtocolHandler.HandshakeComplete)evt;
|
|
||||||
String origin = getDomainName(handshake.requestHeaders().get("Origin"));
|
|
||||||
|
|
||||||
if(!isWhitelisted(origin)) {
|
|
||||||
ctx.channel().writeAndFlush(new CloseWebSocketFrame(403, "Origin forbidden")).addListener(ChannelFutureListener.CLOSE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
super.userEventTriggered(ctx, evt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getDomainName(String url) throws URISyntaxException {
|
|
||||||
URI uri = new URI(url);
|
|
||||||
String domain = uri.getHost();
|
|
||||||
return domain.startsWith("www.") ? domain.substring(4) : domain;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isWhitelisted(String origin) {
|
|
||||||
String[] allowedOrigins = Emulator.getConfig().getValue("websockets.whitelist", "localhost").split(",");
|
|
||||||
for(String entry : allowedOrigins) {
|
|
||||||
if(entry.startsWith("*")) {
|
|
||||||
if(origin.endsWith(entry.substring(1)) || ("." + origin).equals(entry.substring(1))) return true;
|
|
||||||
} else {
|
|
||||||
if(origin.equals(entry)) return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(Emulator.getConfig().getBoolean("debug.mode")) {
|
|
||||||
LOGGER.info("Origin not allowed: " + origin);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,53 @@
|
|||||||
|
package org.krews.plugin.nitro.websockets.handlers;
|
||||||
|
|
||||||
|
import com.eu.habbo.Emulator;
|
||||||
|
import io.netty.buffer.Unpooled;
|
||||||
|
import io.netty.channel.ChannelFutureListener;
|
||||||
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||||
|
import io.netty.handler.codec.http.*;
|
||||||
|
import io.netty.util.ReferenceCountUtil;
|
||||||
|
import org.krews.plugin.nitro.Utils;
|
||||||
|
import org.krews.plugin.nitro.main;
|
||||||
|
|
||||||
|
public class CustomHTTPHandler extends ChannelInboundHandlerAdapter {
|
||||||
|
private static final String ORIGIN_HEADER = "Origin";
|
||||||
|
//private static final String FORWARD_PROXY_REALIP = "X-Forwarded-For";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||||
|
if(msg instanceof HttpMessage) {
|
||||||
|
if(!handleHttpRequest(ctx, (HttpMessage) msg))
|
||||||
|
{
|
||||||
|
ReferenceCountUtil.release(msg);//discard message
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.channelRead(ctx, msg);
|
||||||
|
ctx.pipeline().remove(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean handleHttpRequest(ChannelHandlerContext ctx, HttpMessage req) {
|
||||||
|
String origin = "error";
|
||||||
|
|
||||||
|
try {
|
||||||
|
if(req.headers().contains(ORIGIN_HEADER)) {
|
||||||
|
origin = Utils.getDomainNameFromUrl(req.headers().get(ORIGIN_HEADER));
|
||||||
|
}
|
||||||
|
} catch (Exception ignored) { }
|
||||||
|
|
||||||
|
if(!Utils.isWhitelisted(origin, Emulator.getConfig().getValue("websockets.whitelist", "localhost").split(","))) {
|
||||||
|
FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.FORBIDDEN, Unpooled.wrappedBuffer("Origin forbidden".getBytes()));
|
||||||
|
ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
String header = Emulator.getConfig().getValue("ws.nitro.ip.header", "");
|
||||||
|
|
||||||
|
if(!header.isEmpty() && req.headers().contains(header)) {
|
||||||
|
String ip = req.headers().get(header);
|
||||||
|
ctx.channel().attr(main.WS_IP).set(ip);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user