보안 통신을 위한 다양하고 효율적인 프록시 플랫폼입니다.
splice(2)
사용하는 Linux의 TCP 릴레이 빠른 경로.recvmmsg(2)
및 sendmmsg(2)
를 사용하는 Linux의 UDP 릴레이 빠른 경로. 릴리스 및 VCS 패키지는 AUR에서 사용할 수 있습니다.
릴리스에서 다운로드하십시오.
Go를 사용하여 최신 버전을 빌드하고 설치합니다.
go install github.com/database64128/shadowsocks-go/cmd/shadowsocks-go@latest
go install github.com/database64128/shadowsocks-go/cmd/shadowsocks-go-domain-set-converter@latest
또는 저장소를 복제하고 수동으로 빌드합니다.
go build -trimpath -ldflags ' -s -w ' ./cmd/shadowsocks-go
go build -trimpath -ldflags ' -s -w ' ./cmd/shadowsocks-go-domain-set-converter
모든 구성 예제와 시스템 단위 파일은 docs 디렉터리에서 찾을 수 있습니다.
clients
필드는 생략하거나 비워 둘 수 있습니다. 기본 "직접" 클라이언트가 자동으로 추가됩니다.
프로덕션 서버에서는 udpRelayBatchSize
8과 같은 낮은 값으로 설정하여 메모리 사용량을 줄이면서 여전히 recvmmsg(2)
및 sendmmsg(2)
의 이점을 누릴 수 있습니다.
UDP 패킷은 mtu
에서 계산된 최대 패킷 크기까지 채워질 수 있습니다. PPPoE 연결에서 서버를 사용할 수 있는 경우 mtu
1492로 줄여야 합니다. 클라이언트-서버 PMTU를 알 수 없는 경우 paddingPolicy
NoPadding
으로 설정하여 패딩을 완전히 비활성화할 수 있습니다.
사용자 PSK가 없는 서버(단일 사용자 모드)의 경우 psk
필드는 PSK를 지정하고 uPSKStorePath
필드는 생략하거나 비워 둘 수 있습니다. 하나 이상의 사용자 PSK가 uPSK 저장소 파일에 지정되면 psk
필드는 ID PSK를 지정합니다.
서버를 재시작하지 않고 사용자를 추가/업데이트/삭제하려면 uPSK 스토어 파일을 수정하고 SIGUSR1
신호를 서버 프로세스에 보내거나 RESTful API를 사용하세요. RESTful API의 업데이트는 uPSK 스토어 파일에 자동으로 저장됩니다.
/etc/shadowsocks-go/config.json
{
"servers" : [
{
"name" : " ss-2022 " ,
"listen" : " :20220 " ,
"protocol" : " 2022-blake3-aes-128-gcm " ,
"enableTCP" : true ,
"listenerTFO" : true ,
"enableUDP" : true ,
"mtu" : 1500 ,
"psk" : " qQln3GlVCZi5iJUObJVNCw== " ,
"uPSKStorePath" : " /etc/shadowsocks-go/upsks.json "
}
]
}
/etc/shadowsocks-go/upsks.json
{
"Steve" : " oE/s2z9Q8EWORAB8B3UCxw== " ,
"Alex" : " hWXLOSW/r/LtNKynrA3S8Q== "
}
기본적으로 라우터는 구성된 DNS 서버를 사용하여 도메인 이름을 확인하고 IP 규칙을 일치시킵니다. 확인된 IP 주소는 IP 규칙 일치에만 사용됩니다. 요청은 원래 도메인 이름을 사용하여 이루어집니다. 도메인 이름에 대한 IP 규칙 일치를 비활성화하려면 disableNameResolutionForIPRules
true로 설정합니다.
{
"servers" : [
{
"name" : " socks5 " ,
"listen" : " :1080 " ,
"protocol" : " socks5 " ,
"enableTCP" : true ,
"listenerTFO" : true ,
"enableUDP" : true ,
"mtu" : 1500
},
{
"name" : " http " ,
"listen" : " :8080 " ,
"protocol" : " http " ,
"enableTCP" : true ,
"listenerTFO" : true
}
],
"clients" : [
{
"name" : " ss-2022 " ,
"protocol" : " 2022-blake3-aes-128-gcm " ,
"endpoint" : " [2001:db8:bd63:362c:2071:a0f6:827:ab6a]:20220 " ,
"enableTCP" : true ,
"dialerTFO" : true ,
"enableUDP" : true ,
"mtu" : 1500 ,
"psk" : " oE/s2z9Q8EWORAB8B3UCxw== " ,
"iPSKs" : [
" qQln3GlVCZi5iJUObJVNCw== "
]
},
{
"name" : " direct " ,
"protocol" : " direct " ,
"enableTCP" : true ,
"dialerTFO" : true ,
"enableUDP" : true ,
"mtu" : 1500
}
],
"dns" : [
{
"name" : " cf-v6 " ,
"addrPort" : " [2606:4700:4700::1111]:53 " ,
"tcpClientName" : " ss-2022 " ,
"udpClientName" : " ss-2022 "
},
{
"name" : " system " ,
"type" : " system "
}
],
"router" : {
"defaultTCPClientName" : " ss-2022 " ,
"defaultUDPClientName" : " ss-2022 " ,
"geoLite2CountryDbPath" : " /usr/share/shadowsocks-go/Country.mmdb " ,
"domainSets" : [
{
"name" : " category-ads-all " ,
"type" : " gob " ,
"path" : " /usr/share/shadowsocks-go/ss-go-gob-category-ads-all "
},
{
"name" : " private " ,
"type" : " gob " ,
"path" : " /usr/share/shadowsocks-go/ss-go-gob-private "
},
{
"name" : " cn " ,
"type" : " gob " ,
"path" : " /usr/share/shadowsocks-go/ss-go-gob-cn "
},
{
"name" : " geolocation-!cn@cn " ,
"type" : " gob " ,
"path" : " /usr/share/shadowsocks-go/ss-go-gob-geolocation-!cn@cn "
}
],
"routes" : [
{
"name" : " ads " ,
"client" : " reject " ,
"toDomainSets" : [
" category-ads-all "
]
},
{
"name" : " direct " ,
"client" : " direct " ,
"resolver" : " cf-v6 " ,
"toDomainSets" : [
" private " ,
" cn "
],
"toPrefixes" : [
" 0.0.0.0/8 " ,
" 10.0.0.0/8 " ,
" 100.64.0.0/10 " ,
" 127.0.0.0/8 " ,
" 169.254.0.0/16 " ,
" 172.16.0.0/12 " ,
" 192.0.0.0/24 " ,
" 192.0.2.0/24 " ,
" 192.88.99.0/24 " ,
" 192.168.0.0/16 " ,
" 198.18.0.0/15 " ,
" 198.51.100.0/24 " ,
" 203.0.113.0/24 " ,
" 224.0.0.0/3 " ,
" ::1/128 " ,
" fc00::/7 " ,
" fe80::/10 " ,
" ff00::/8 "
],
"toGeoIPCountries" : [
" CN "
]
},
{
"name" : " cn-verify-ip " ,
"client" : " direct " ,
"resolver" : " system " ,
"toDomainSets" : [
" geolocation-!cn@cn "
],
"toMatchedDomainExpectedGeoIPCountries" : [
" CN "
]
}
]
}
}
docs/config.json을 참조하세요.
Shadowsocks-go에는 자체 도메인 세트 파일 형식이 있습니다. 제가 본 다른 형식은 모두 끔찍하기 때문입니다!
그리고 걱정하지 마세요. 다양한 형식 간에 변환할 수 있는 간단한 변환 도구가 있습니다: Shadowsocks-go-domain-set-converter
도메인 세트 텍스트 파일은 선택적으로 용량 힌트 설명으로 시작됩니다. 변환 도구는 용량 힌트를 자동으로 생성할 수 있습니다. 도메인 일치 규칙에는 4가지 유형이 있습니다.
domain:
도메인을 일치시킵니다.suffix:
도메인과 해당 하위 도메인을 일치시킵니다.keyword:
도메인에 키워드가 포함된 경우 일치합니다.regexp:
도메인이 정규식과 일치하면 일치합니다.도메인 세트 텍스트 파일의 예:
# shadowsocks-go domain set capacity hint 1 6 1 1 DSKR
domain:www.example.net
suffix:example.com
suffix:github.com
suffix:cube64128.xyz
suffix:api.ipify.org
suffix:api6.ipify.org
suffix:archlinux.org
keyword:dev
regexp:^adservice.google.([a-z]{2}|com?)(.[a-z]{2})?$
도메인 세트 텍스트 파일을 로드할 때 Shadowsocks-go는 모든 접미사를 있는 그대로 단일 맵에 로드합니다. 이를 통해 시작 속도, 메모리 사용량 및 일치 속도 간의 최상의 균형을 달성할 수 있습니다. 더 나은 성능을 원한다면 변환 도구를 사용하여 텍스트 파일을 gob 형식으로 변환할 수 있습니다.
gob 형식은 기본적으로 동일하지만 모든 바이너리가 직렬화되어 있고 trie를 사용하여 접미사를 저장하고 일치시킵니다. 변환 도구는 접미사 트리를 작성하기 위해 접미사를 로드한 다음 트리 및 기타 규칙을 gob 파일로 직렬화합니다. 꽤 깔끔하지 않나요?
물론 저는 알고리즘 전문가가 아니기 때문에 전체 프로세스에는 여전히 비효율성이 많이 있습니다. 그러나 그것은 나에게 충분합니다. 새롭고 멋진 아이디어가 있다면 알려주세요!
일반적으로 사용되는 도메인 세트 세트는 릴리스 분기의 Shadowsocks-go-domain-sets에서 매주 업데이트됩니다. Arch Linux 사용자는 AUR에서 Shadowsocks-go-domain-sets-git 패키지를 설치할 수 있습니다.
https://github.com/v2fly/domain-list-community를 소스로 사용하여 도메인 세트를 생성하려면 리포지토리를 복제하고 생성기를 빌드한 다음 일반 텍스트 목록을 생성하십시오.
./domain-list-community -exportlists ' google,netflix '
일반 텍스트 목록을 도메인 세트 파일로 변환하려면 shadowsocks-go-domain-set-converter
사용하십시오.
shadowsocks-go-domain-set-converter -inDlc google.txt -outGob ss-go-gob-google
shadowsocks-go-domain-set-converter -inDlc netflix.txt -outGob ss-go-gob-netflix
Shadowsocks-go는 IP 위치정보를 위해 MaxMind GeoLite2 국가 데이터베이스를 사용합니다. 데이터베이스는 https://github.com/Dreamacro/maxmind-geoip에서 다운로드할 수 있습니다. Arch Linux 사용자는 AUR에서 Shadowsocks-go-geolite2-country-git 패키지를 설치할 수 있습니다.
Shadowsocks 2022 프로토콜에 대해 패킷 패딩 정책이 구현됩니다. 패킷 패딩 정책은 나가는 패킷에 패딩을 추가할지 여부를 제어합니다.
패딩을 추가할 때 MTU가 고려되므로 패딩된 패킷의 크기는 MTU를 초과하지 않습니다. 따라서 MTU를 올바르게 설정하는 것이 중요합니다.
패딩 정책은 각 Shadowsocks 2022 클라이언트 및 서버에 대해 개별적으로 구성할 수 있습니다.
PadPlainDNS
: 대상 포트가 53인 경우 패딩을 추가합니다. (기본값)PadAll
: 모든 패킷을 채웁니다.NoPadding
: 패딩이 없습니다.거부 정책은 모든 TCP 서버에 대해 구현됩니다. TCP 서버의 거부 정책은 허용된 연결이 프로토콜의 핸드셰이크 프로세스에 실패할 때 호출됩니다. 각 프로토콜에는 자체 기본 거부 정책이 있습니다. 검열 우회 서버가 활성 프로브를 회피하는 데 사용자 지정 거부 정책이 유용할 수 있습니다.
JustClose
: 연결을 닫으면 됩니다. (일반 텍스트 프로토콜의 기본값)ForceReset
: 연결을 강제로 재설정합니다. 유효하지 않은 데이터가 수신되면 많은 프로토콜이 이런 방식으로 동작합니다. (Shadowsocks 2022의 기본값)CloseWriteDrain
: FIN을 보내고 EOF까지 계속 읽습니다. 이는 일반적으로 레거시 Shadowsocks 서버가 재생을 처리하는 방식입니다.ReplyWithGibberish
: 읽기를 계속하고 각 읽기가 반환된 후 임의의 쓰레기를 보냅니다. 이는 재생된 페이로드를 실제로 릴레이하지 않는다는 점을 제외하고 재생 보호 기능이 없는 레거시 Shadowsocks 서버의 작동 방식을 에뮬레이트합니다. Shadowsocks 2022 서버는 핸드셰이크가 실패할 경우 대체 주소로 TCP 연결을 전달하도록 구성할 수 있습니다. unsafeFallbackAddress
필드를 서버 블록에 추가하여 대체 주소를 지정합니다. 시작 시 이 기능을 사용하면 서버가 "오염"된다는 경고 메시지가 인쇄됩니다. 안전하지 않은 대체는 TCP 연결에서만 작동합니다.
이 기능은 위협 모델에 경로를 벗어난 공격자만 포함되어 있고 포트를 재사용하거나 프로브를 속여 서버가 다른 것으로 생각하도록 하려는 경우에 유용할 수 있습니다. 경로 상의 공격자(예: 일반적인 검열관)는 일반 트래픽이 대체 트래픽과 일치하지 않는다는 것을 쉽게 알 수 있습니다.
안전하지 않은 스트림 접두사 기능을 사용하면 Shadowsocks 2022 스트림에 대해 사전 공유된 일반 텍스트 접두사 쌍을 구성할 수 있습니다. 접두사는 간단한 방화벽을 속이기 위해 요청 및 응답 스트림 앞에 추가됩니다.
이 기능을 사용하려면 클라이언트와 서버 블록 모두에 unsafeRequestStreamPrefix
및 unsafeResponseStreamPrefix
추가하고 base64 인코딩에 접두사를 지정합니다. 클라이언트와 서버는 동일한 접두사 쌍에 동의해야 합니다. 시작 시 이 기능을 사용하면 클라이언트와 서버가 "오염"된다는 경고 메시지가 인쇄됩니다.
AGPL-3.0 이상