Skip to content

Commit

Permalink
Merge pull request #28 from Zmax0/dev/2.5.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Zmax0 committed Jul 11, 2024
2 parents 8452ac8 + a9c0644 commit e389618
Show file tree
Hide file tree
Showing 74 changed files with 1,498 additions and 415 deletions.
72 changes: 46 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,37 @@

[![codecov](https://codecov.io/gh/Zmax0/urban-spork/branch/master/graph/badge.svg?token=6QAZQ05HZV)](https://codecov.io/gh/Zmax0/urban-spork)

A sock5 proxy
A network tool for improved privacy and security

## Features

### Local

- http
- socks5

### Transport

| | Shadowsocks | VMess | Trojan |
|:--------------|:-----------:|:-----:|:------:|
| tcp ||||
| udp ||||
| ws(WebSocket) ||| |

### Ciphers

| | Shadowsocks | VMess |
|:------------------------|:-----------:|:-------:|
| aes-128-gcm | `C` `S` | `C` `S` |
| aes-256-gcm | `C` `S` | |
| chacha20-poly1305 | `C` `S` | `C` `S` |
| 2022-blake3-aes-128-gcm | `C` `S` | |
| 2022-blake3-aes-256-gcm | `C` `S` | |

`C` for client `S` for server

## Config

put *config.json* file into the unpacked folder before running server

```json5
Expand Down Expand Up @@ -32,6 +60,12 @@ put *config.json* file into the unpacked folder before running server
"keyFile": "/path/to/private.key",
"keyPassword": "",
"serverName": ""
},
"ws": {
"header": {
"Host": "example.com"
},
"path": "/ws"
}
}
]
Expand All @@ -46,40 +80,26 @@ put *config.json* file into the unpacked folder before running server
> `packetEncoding`: "None" | "Packet"
> `user`: (OPTIONAL for shadowsocks) support multiple users with [*Shadowsocks 2022 Extensible Identity Headers*](https://github.com/Shadowsocks-NET/shadowsocks-specs/blob/main/2022-2-shadowsocks-2022-extensible-identity-headers.md)
> `user`: (OPTIONAL for shadowsocks) support multiple users with [*Shadowsocks 2022 Extensible Identity
Headers*](https://github.com/Shadowsocks-NET/shadowsocks-specs/blob/main/2022-2-shadowsocks-2022-extensible-identity-headers.md)

> `sslSetting`: (REQUIRED for trojan) SSL specific configurations
> `ssl`: (OPTIONAL) SSL specific configurations
>> `certificateFile`: certificate file
> > `certificateFile`: certificate file
>> `keyFile`: private key file for encryption
> > `keyFile`: private key file for encryption
>> `keyPassword`: password of the private key file
> > `keyPassword`: password of the private key file
>> `serverName`: the Server Name Indication field in the SSL handshake. If left blank, it will be set to `server.host`
> > `serverName`: the Server Name Indication field in the SSL handshake. If left blank, it will be set to `server.host`
>> `verifyHostname`: whether to verify SSL hostname, default is `true`
> > `verifyHostname`: whether to verify SSL hostname, default is `true`
## Features
> `ws`: (OPTIONAL) WebSocket specific configurations
### Transport
> > `header`: the header to be sent in HTTP request, should be key-value pairs in clear-text string format
| | Shadowsocks | VMess | Trojan |
|:----|:-----------:|:-----:|:------:|
| TCP ||||
| UDP ||||

### Ciphers

| | Shadowsocks | VMess |
|:------------------------|:-----------:|:-------:|
| aes-128-gcm | `C` `S` | `C` `S` |
| aes-256-gcm | `C` `S` | |
| chacha20-poly1305 | `C` `S` | `C` `S` |
| 2022-blake3-aes-128-gcm | `C` `S` | |
| 2022-blake3-aes-256-gcm | `C` `S` | |

`C` for client `S` for server
> > `path`: the HTTP path for the websocket request
## Build

Expand Down
16 changes: 13 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>urban-spork</groupId>
<artifactId>urban-spork</artifactId>
<version>2.4.5</version>
<version>2.5.0</version>
<packaging>pom</packaging>
<modules>
<module>urban-spork-common</module>
Expand All @@ -14,7 +14,7 @@
</modules>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<urban-spork.version>2.4.5</urban-spork.version>
<urban-spork.version>2.5.0</urban-spork.version>
<maven-surefire-plugin.versioin>3.2.5</maven-surefire-plugin.versioin>
<maven-jar-plugin.version>3.4.1</maven-jar-plugin.version>
<maven-compiler-plugin.version>3.13.0</maven-compiler-plugin.version>
Expand All @@ -23,7 +23,7 @@
<jackson.version>2.17.1</jackson.version>
<logback.version>1.5.6</logback.version>
<netty.version>4.1.110.Final</netty.version>
<bouncycastle.version>2.73.6</bouncycastle.version>
<bouncycastle.version>2.73.5</bouncycastle.version>
<javafx.version>22.0.1</javafx.version>
<jfoenix.version>9.0.10</jfoenix.version>
</properties>
Expand Down Expand Up @@ -75,11 +75,21 @@
<artifactId>netty-codec-socks</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec-http</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-lts8on</artifactId>
<version>${bouncycastle.version}</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-lts8on</artifactId>
<version>${bouncycastle.version}</version>
</dependency>
<dependency>
<groupId>com.jfoenix</groupId>
<artifactId>jfoenix</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion urban-spork-client-gui/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<parent>
<groupId>urban-spork</groupId>
<artifactId>urban-spork</artifactId>
<version>2.4.5</version>
<version>2.5.0</version>
</parent>
<groupId>urban-spork-client-gui</groupId>
<artifactId>urban-spork-client-gui</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion urban-spork-client-gui/resource/startup.cmd
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@echo off
set server="urban-spork-client-gui"
start javaw --add-opens java.base/java.lang.reflect=ALL-UNNAMED -jar %server%.jar
start javaw --add-opens java.base/java.lang.reflect=com.jfoenix --add-opens javafx.controls/com.sun.javafx.scene.control.behavior=com.jfoenix --add-opens javafx.controls/com.sun.javafx.scene.control=com.jfoenix -jar %server%.jar
exit
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,10 @@ public class Resource {
public static final URL CONSOLE_CSS;

static {
ClassLoader classLoader = Resource.class.getClassLoader();
String resourcePath = "resource/";
PROGRAM_ICON = Objects.requireNonNull(classLoader.getResource(resourcePath + PROGRAM_ICON_NAME));
TRAY_ICON = Objects.requireNonNull(classLoader.getResource(resourcePath + TRAY_ICON_NAME));
CONSOLE_CSS = Objects.requireNonNull(classLoader.getResource(resourcePath + CONSOLE_CSS_NAME));
String resourcePath = "/resource/";
PROGRAM_ICON = Objects.requireNonNull(Resource.class.getResource(resourcePath + PROGRAM_ICON_NAME));
TRAY_ICON = Objects.requireNonNull(Resource.class.getResource(resourcePath + TRAY_ICON_NAME));
CONSOLE_CSS = Objects.requireNonNull(Resource.class.getResource(resourcePath + CONSOLE_CSS_NAME));
ClientConfig config = ConfigHandler.DEFAULT.read();
if (config == null) {
config = new ClientConfig();
Expand Down
17 changes: 17 additions & 0 deletions urban-spork-client-gui/src/module-info.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module com.urbanspork.client.gui {
requires ch.qos.logback.classic;
requires ch.qos.logback.core;
requires com.fasterxml.jackson.databind;
requires com.jfoenix;
requires com.urbanspork.client;
requires com.urbanspork.common;
requires io.netty.handler;
requires java.desktop;
requires javafx.base;
requires javafx.controls;
requires javafx.graphics;
requires org.slf4j;

exports com.urbanspork.client.gui.console to javafx.graphics, ch.qos.logback.core;
exports com.urbanspork.client.gui.tray to javafx.graphics, ch.qos.logback.core;
}
2 changes: 1 addition & 1 deletion urban-spork-client/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<parent>
<groupId>urban-spork</groupId>
<artifactId>urban-spork</artifactId>
<version>2.4.5</version>
<version>2.5.0</version>
</parent>
<artifactId>urban-spork-client</artifactId>
<dependencies>
Expand Down
2 changes: 1 addition & 1 deletion urban-spork-client/src/com/urbanspork/client/Client.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public static void launch(ClientConfig config, CompletableFuture<Instance> promi
.childOption(ChannelOption.SO_KEEPALIVE, true) // socks5 require
.childOption(ChannelOption.TCP_NODELAY, false)
.childOption(ChannelOption.SO_LINGER, 1)
.childHandler(new ClientSocksInitializer(current))
.childHandler(new ClientInitializer(current))
.bind(InetAddress.getLoopbackAddress(), config.getPort()).sync().addListener((ChannelFutureListener) future -> {
ServerSocketChannel tcp = (ServerSocketChannel) future.channel();
InetSocketAddress tcpLocalAddress = tcp.localAddress();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.urbanspork.client;

import com.urbanspork.common.util.HttpProxyUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.HttpMethod;

import java.util.function.Consumer;

@ChannelHandler.Sharable
class ClientHttpUnificationHandler extends SimpleChannelInboundHandler<ByteBuf> {
static final ClientHttpUnificationHandler INSTANCE = new ClientHttpUnificationHandler();

private ClientHttpUnificationHandler() {}

@Override
public void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) {
HttpProxyUtil.Option option = HttpProxyUtil.parseOption(msg);
if (HttpMethod.GET == option.method()) {
new HttpRelayHandler(msg.retain()).connect(ctx.channel(), option.address());
} else {
new HttpsRelayHandler().connect(ctx.channel(), option.address());
}
}

private record HttpRelayHandler(ByteBuf msg) implements ClientTcpRelayHandler {
@Override
public ChannelHandler inboundHandler() {
return INSTANCE;
}

@Override
public InboundWriter inboundWriter() {
return new InboundWriter(channel -> {}, channel -> {});
}

@Override
public Consumer<Channel> outboundWriter() {
return channel -> channel.writeAndFlush(msg);
}
}

private static class HttpsRelayHandler implements ClientTcpRelayHandler {
private static final byte[] SUCCESS = "HTTP/1.1 200 Connection established\r\n\r\n".getBytes();
private static final byte[] FAILED = "HTTP/1.1 500 Internal Server Error\r\n\r\n".getBytes();

@Override
public ChannelHandler inboundHandler() {
return INSTANCE;
}

@Override
public InboundWriter inboundWriter() {
return new InboundWriter(
channel -> channel.writeAndFlush(Unpooled.wrappedBuffer(SUCCESS)),
channel -> channel.writeAndFlush(Unpooled.wrappedBuffer(FAILED))
);
}

@Override
public Consumer<Channel> outboundWriter() {
return channel -> {};
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.urbanspork.client;

import com.urbanspork.common.channel.AttributeKeys;
import com.urbanspork.common.config.ServerConfig;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.nio.NioSocketChannel;

class ClientInitializer extends ChannelInitializer<NioSocketChannel> {

private final ServerConfig config;

ClientInitializer(ServerConfig config) {
this.config = config;
}

@Override
protected void initChannel(NioSocketChannel channel) {
channel.attr(AttributeKeys.SERVER_CONFIG).set(config);
channel.pipeline().addLast(config.getTrafficShapingHandler(), new ClientProxyUnificationHandler());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.urbanspork.client;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.handler.codec.socksx.SocksPortUnificationServerHandler;
import io.netty.handler.codec.socksx.SocksVersion;

import java.util.List;

class ClientProxyUnificationHandler extends ByteToMessageDecoder {
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
SocksVersion version = SocksVersion.valueOf(in.getByte(in.readerIndex()));
ChannelPipeline p = ctx.pipeline();
if (version == SocksVersion.UNKNOWN) {
p.addLast(ClientHttpUnificationHandler.INSTANCE);
} else {
p.addLast(new SocksPortUnificationServerHandler(), ClientSocksMessageHandler.INSTANCE);
}
p.remove(this);
}
}
Loading

0 comments on commit e389618

Please sign in to comment.