1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.example.socksproxy;
17
18 import io.netty.channel.ChannelHandler;
19 import io.netty.channel.ChannelHandlerContext;
20 import io.netty.channel.SimpleChannelInboundHandler;
21 import io.netty.handler.codec.socksx.SocksMessage;
22 import io.netty.handler.codec.socksx.v4.Socks4CommandRequest;
23 import io.netty.handler.codec.socksx.v4.Socks4CommandType;
24 import io.netty.handler.codec.socksx.v5.DefaultSocks5InitialResponse;
25 import io.netty.handler.codec.socksx.v5.DefaultSocks5PasswordAuthResponse;
26 import io.netty.handler.codec.socksx.v5.DefaultSocks5PrivateAuthResponse;
27 import io.netty.handler.codec.socksx.v5.Socks5AuthMethod;
28 import io.netty.handler.codec.socksx.v5.Socks5InitialRequest;
29 import io.netty.handler.codec.socksx.v5.Socks5CommandRequest;
30 import io.netty.handler.codec.socksx.v5.Socks5CommandRequestDecoder;
31 import io.netty.handler.codec.socksx.v5.Socks5CommandType;
32 import io.netty.handler.codec.socksx.v5.Socks5PasswordAuthRequest;
33 import io.netty.handler.codec.socksx.v5.Socks5PasswordAuthStatus;
34 import io.netty.handler.codec.socksx.v5.Socks5PrivateAuthRequest;
35 import io.netty.handler.codec.socksx.v5.Socks5PrivateAuthStatus;
36
37 @ChannelHandler.Sharable
38 public final class SocksServerHandler extends SimpleChannelInboundHandler<SocksMessage> {
39
40 public static final SocksServerHandler INSTANCE = new SocksServerHandler();
41
42 private SocksServerHandler() { }
43
44 @Override
45 public void channelRead0(ChannelHandlerContext ctx, SocksMessage socksRequest) throws Exception {
46 switch (socksRequest.version()) {
47 case SOCKS4a:
48 Socks4CommandRequest socksV4CmdRequest = (Socks4CommandRequest) socksRequest;
49 if (socksV4CmdRequest.type() == Socks4CommandType.CONNECT) {
50 ctx.pipeline().addLast(new SocksServerConnectHandler());
51 ctx.pipeline().remove(this);
52 ctx.fireChannelRead(socksRequest);
53 } else {
54 ctx.close();
55 }
56 break;
57 case SOCKS5:
58 if (socksRequest instanceof Socks5InitialRequest) {
59
60
61
62 ctx.pipeline().addFirst(new Socks5CommandRequestDecoder());
63 ctx.write(new DefaultSocks5InitialResponse(Socks5AuthMethod.NO_AUTH));
64 } else if (socksRequest instanceof Socks5PasswordAuthRequest) {
65 ctx.pipeline().addFirst(new Socks5CommandRequestDecoder());
66 ctx.write(new DefaultSocks5PasswordAuthResponse(Socks5PasswordAuthStatus.SUCCESS));
67 } else if (socksRequest instanceof Socks5PrivateAuthRequest) {
68 ctx.pipeline().addFirst(new Socks5CommandRequestDecoder());
69 ctx.write(new DefaultSocks5PrivateAuthResponse(Socks5PrivateAuthStatus.SUCCESS));
70 } else if (socksRequest instanceof Socks5CommandRequest) {
71 Socks5CommandRequest socks5CmdRequest = (Socks5CommandRequest) socksRequest;
72 if (socks5CmdRequest.type() == Socks5CommandType.CONNECT) {
73 ctx.pipeline().addLast(new SocksServerConnectHandler());
74 ctx.pipeline().remove(this);
75 ctx.fireChannelRead(socksRequest);
76 } else {
77 ctx.close();
78 }
79 } else {
80 ctx.close();
81 }
82 break;
83 case UNKNOWN:
84 ctx.close();
85 break;
86 }
87 }
88
89 @Override
90 public void channelReadComplete(ChannelHandlerContext ctx) {
91 ctx.flush();
92 }
93
94 @Override
95 public void exceptionCaught(ChannelHandlerContext ctx, Throwable throwable) {
96 throwable.printStackTrace();
97 SocksServerUtils.closeOnFlush(ctx.channel());
98 }
99 }