Giter VIP home page Giter VIP logo

shadowsocks-net's Introduction

Overview

Shadowsocks-Net is a cross-platform version of Shadowsocks developed in C# (.NET Core).

中文

Version

Shadowsocks-Net plans to release multiple versions, the feature comparison is shown in the table below.

Completion
of
development
Version ss-local ss-remote Local
HTTP1
Obfuscation URL/IP
filtering
Server
scheduling
strategy
GUI
90% Minimal-
cross-platform
10% Windows
1% Linux

The Minimal vesion is available for testing now, supported encryption algorithms:

aes-256-gcm, aes-192-gcm, aes-128-gcm, chacha20-ietf-poly1305, xchacha20-ietf-poly1305

Development Instructions

Schematic diagram of architecture

arch

Shadowsocks-Net encapsulates the network programming part simply so that the upper layer can focus on the socks5 protocol. Since Shadowsocks mainly implements socks5 protocol, the upper layer code is now very thin. Socks5 generally only do two things: 1. negotiation, 2. forwarding. Shadowsocks-Net tries to make developing Shadowsocks in C# more enjoyable and easier.

Master branch is a classical implementation of Shadowsocks. The pluggable-tunnel branch has a slightly different architecture, which gives flexibility to integrate multiplexed tunnels.


Steps to add encryption algorithm

  1. Implement the unified encryption interface IShadowsocksAeadCipher or IShadowsocksStreamCipher
class MyCipher : IShadowsocksAeadCipher
{
    //implementation
}
  1. Mark with Cipher attribute
[Cipher("my-cipher-name")]
class MyCipher : IShadowsocksAeadCipher
{
    //implementation
}

MyCipher is recognized now.


Obfuscation support

Obfuscation is similar to encryption, in Shadowsocks-Net, it works as a filter. The logic of obfuscation can be more complicated than encryption. But as the other parts have been encapsulated, now only need to focus on reading and writing the network stream, and implement a ClientFilter.

public interface IClientReaderFilter
{
    ClientFilterResult OnReading(ClientFilterContext filterContext);
}
public interface IClientWriterFilter
{
    ClientFilterResult OnWriting(ClientFilterContext filterContext);        
}

Encryption, obfuscation and UDP encapsulation are all implemented by filters in Shadowsocks-Net. Filters are pluggable. Therefore, filters can also be used to interpret custom protocols.

The following filter inserts four bytes 0x12, 0x34, 0xAB, 0xCD into the beginning of the data each time before sending, and correspondingly skips the first four bytes when receiving:

class TestClientFilter : ClientFilter
{
    public override ClientFilterResult OnWriting(ClientFilterContext ctx)
    {
        byte[] data = ctx.Memory.ToArray();
        byte[] newData = new byte[data.Length + 4];
        newData[0] = 0x12;
        newData[1] = 0x34;
        newData[2] = 0xAB;
        newData[3] = 0xCD;
        Array.Copy(data, 0, newData, 4, data.Length);
        return new ClientFilterResult(ctx.Client, newData, ...);
    }

    public override ClientFilterResult OnReading(ClientFilterContext ctx)
    {
        byte[] data = ctx.Memory.ToArray();
        byte[] newData = data.Skip(4).ToArray();
        return new ClientFilterResult(ctx.Client, newData, ...);
    }
}

Steps to create filter
  1. Choose the proper Category and Priority, which determine the order of the filter in the filter chain. The framework has preseted several categories:
    public enum ClientFilterCategory
    {
        Obfuscation = 1,
        Cipher = 2,
        Encapsulation = 3,
        Custom = 4
    }
  1. Inherit ClientFilter
    public abstract class ClientFilter
    {
        public abstract ClientFilterResult OnReading(ClientFilterContext filterContext);
        public abstract ClientFilterResult OnWriting(ClientFilterContext filterContext);
    }
  1. Add filter to pipe
    DuplexPipe.AddFilter(IClient client, IClientFilter filter);

A typical case: UdpEncapsulationFilter.cs.

Support for protocols other than TCP or UDP

As interfaces have already been abstracted by design, other communication protocols can now also be integrated. Just implement IClient and IServer, no need to change other parts.

IClient and IServer are also simple:

public partial interface IClient : IPeer
{        
    ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default);
    ValueTask<int> WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = default);
    
    IPEndPoint LocalEndPoint { get; }
    void Close();
    event EventHandler<ClientEventArgs> Closing;
}
public interface IServer : IPeer
{
    void Listen();
    void StopListen();
}
public interface IServer<TClient> : IServer
    where TClient : IClient
{
    Task<TClient> Accept();       
}

For instance, in order to integrate the KCP protocol, we implemented KcpClient and KcpServer, then Shadowsocks-Net uses KCP as the transport layer protocol.

Compile

Environment and dependence

Visual Studio 2019 Community, .NET Framework 4.6 (temporarily used to design winform), .NET Standard 2.1 & .NET 5.0.

How to compile

Simply build the entire solution in Visual Studio.
This project is currently written 100% in C#, the core is .NET Standard 2.1 class library.


Roadmap

Task list

  • ☑ Core rewrite
  • ☐ Windows end
  • ☐ Unified filter rule
  • ☐ Target IP, domain check
  • ☐ Linux version

Usage

Similar to using other versions of Shadowsocks.
The Minimal version has been tested on Windows and Debian10 x64, the parameters are configured through configuration file.

Take an example on Windows:
On server side, edit config.json, run shadowsocks-net-remote.exe:

{
  //"server_host": null,
  "server_port": 6666,
  "use_ipv6": false,
  "timeout": 5,
  "password": "password1",
  "method": "aes-128-gcm"
}

On local side, edit servers.json and app-config.json, run shadowsocks-net-local.exe:

[
  {
    "remarks": "Test Server",
    "server": "10.10.10.102",
    "server_port": 6666,
    "password": "password1",
    "method": "aes-128-gcm",
    "obfs": null,
    "category": null
  }
]
{
 "Socks5Proxy": {
    "Port": 2080,
    "UseIPv6Address": false,
    "UseLoopbackAddress": true
  },
  "HttpProxy": {
    "Port": 8080,
    "UseIPv6Address": false,
    "UseLoopbackAddress": true
  }
}

Resemble on Linux. Installing .NET Core Portal.

Contribute

There is still a lot of code waiting to be added.




Local HTTP: Transform socks5 into HTTP.

shadowsocks-net's People

Contributors

ohsorry avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

shadowsocks-net's Issues

移植到 UWP 平台的可行性探讨

  1. 基于原生 UWP VPN API
    之前 @Noisyfoxshadowsocks/shadowsocks-windows#862 表示微软没有把文档放出来。事实上 MSDN 文档已经有了,只是描述不够清晰,也没有例子。按照前人在 iOS 上的做法,我大概有了一点点思路,但目前并没有着手实现。欢迎一起探讨。
  2. 桌面到通用 Windows 平台 (UWP) 桥
    如果完全抛弃移动版用户,用这种方法也许可以少走些弯路,不过要牺牲掉一些 Win32 特性。

利益相关: Lumia 640 用户

New features

I need the server to count the number of clients online and the traffic usage of each client, and actively disconnect a client.

Unarchive the repository

@ohsorry created the .Net Core version of Shadowsocks with newly designed architect. This new born repository provides a lot of possibilities to the community and should not be archived.

"dotnet run" error after modify "config.json"

After I modify the "config.json", it report this error when I do "dotnet run".
OS: CentOS 8.
donet version: 3.1.101

Unhandled exception. System.Text.Json.JsonException: The JSON value could not be converted to System.Byte. Path: $.timeout | LineNumber: 4 | BytePositionInLine: 17.
---> System.FormatException: Either the JSON value is not in a supported format, or is out of bounds for an unsigned byte.
at System.Text.Json.Utf8JsonReader.GetByte() in //src/System.Text.Json/src/System/Text/Json/Reader/Utf8JsonReader.TryGet.cs:line 135
at System.Text.Json.Serialization.Converters.JsonConverterByte.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options) in /
/src/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonValueConverterByte.cs:line 11
at System.Text.Json.JsonPropertyInfoNotNullable`4.OnRead(ReadStack& state, Utf8JsonReader& reader) in //src/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfoNotNullable.cs:line 25
at System.Text.Json.JsonPropertyInfo.Read(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader) in /
/src/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfo.cs:line 457
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack) in //src/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.cs:line 50
--- End of inner exception stack trace ---
at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& readStack, Utf8JsonReader& reader, Exception ex) in /
/src/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs:line 161
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack) in //src/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.cs:line 128
at System.Text.Json.JsonSerializer.ReadCore(Type returnType, JsonSerializerOptions options, Utf8JsonReader& reader) in /
/src/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Helpers.cs:line 19
at System.Text.Json.JsonSerializer.Deserialize(String json, Type returnType, JsonSerializerOptions options) in //src/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.String.cs:line 89
at System.Text.Json.JsonSerializer.Deserialize[TValue](String json, JsonSerializerOptions options) in /
/src/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.String.cs:line 31
at Shadowsocks_Minimal_Crossplatform_Remote.Program.Main(String[] args) in /root/Shadowsocks-Net/Shadowsocks-Net/Minimal/Shadowsocks-Minimal-CrossPlatform-Remote/Program.cs:line 61
at Shadowsocks_Minimal_Crossplatform_Remote.Program.

(String[] args)

Consider targeting a lower .NET Standard version

Is your feature request related to a problem? Please describe.
YtFlow is a UWP VPN app that includes an own-created Shadowsocks implementation. In the future, it may be adapted to use this project as a dependency.
In order to make YtFlow runnable on Windows Mobile family, the minimum Windows SDK version is set to 10.0.15063. Therefore, the maximum compatible .NET Standard version is 1.4 according to .NET implementation support. However, this project targets .NET Standard 2.1 which is impossible for YtFlow to consume directly.

Describe the solution you'd like
Consider including both .NET Standard 2.1 and a version at most 1.4 as the target frameworks of this project. For the API invocations that rely on .NET Standard 2.1 only, use conditional code as described in Target frameworks in SDK-style projects.

Describe alternatives you've considered
Would be better if Infrastructure becomes an independent project without any platform-dependent features (even Socket or SslStream) and leave only Stream-related APIs.

Additional context
See YtFlow/YtFlowTunnel

不支持post指令

简要描述 Bug

使用HTTP代理的时候URL使用Post方式提交,不能正常工作,比如在内部建立如下网络:
Debian 10 X64,使用python版本的官方SSServer
windows 7 X64,使用当前项目
这种网络情况下访问内部网络的无线路由器,192.168.1.1,可以显示登录页面。但是无法登录,跟踪日志在提交密码登录的时候,采用post方式,代理服务器没有响应

环境

  • 程序版本: 当前Master版本
  • 系统版本(例如 Windows 10 1903): Windows 7 SP1 X64
  • .NET 版本(例如 Mono 6.8.0): .net core 3.1

如何触发 Bug

1.在内部建立如下网络:
Debian 10 X64,使用python版本的官方SSServer
windows 7 X64,使用当前项目
这种网络情况下访问内部网络的无线路由器,192.168.1.1,可以显示登录页面。但是无法登录,跟踪日志在提交密码登录的时候,采用post方式,代理服务器没有响应

应该发生什么

按道理能正常登录的

日志和截图(如果适用)

PASTE LOG HERE

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.