diff --git a/core/src/foss/golang/go.mod b/core/src/foss/golang/go.mod index bbdff76d..84a7269b 100644 --- a/core/src/foss/golang/go.mod +++ b/core/src/foss/golang/go.mod @@ -9,22 +9,24 @@ require ( github.com/Dreamacro/clash v1.7.1 // indirect github.com/Dreamacro/go-shadowsocks2 v0.1.7 // indirect github.com/dlclark/regexp2 v1.4.0 // indirect - github.com/gofrs/uuid v4.0.0+incompatible // indirect + github.com/gofrs/uuid v4.1.0+incompatible // indirect github.com/gorilla/websocket v1.4.2 // indirect - github.com/insomniacslk/dhcp v0.0.0-20210827173440-b95caade3eac // indirect - github.com/kr328/tun2socket-lwip v0.0.0-20211015022349-94b5374d46e5 // indirect + github.com/insomniacslk/dhcp v0.0.0-20211026125128-ad197bcd36fd // indirect + github.com/kr/pretty v0.1.0 // indirect + github.com/kr328/tun2socket v0.0.0-20211114060954-370f53a7d3d7 // indirect github.com/miekg/dns v1.1.43 // indirect github.com/oschwald/geoip2-golang v1.5.0 // indirect github.com/oschwald/maxminddb-golang v1.8.0 // indirect github.com/sirupsen/logrus v1.8.1 // indirect - github.com/u-root/uio v0.0.0-20210528114334-82958018845c // indirect + github.com/u-root/uio v0.0.0-20210528151154-e40b768296a7 // indirect go.etcd.io/bbolt v1.3.6 // indirect go.uber.org/atomic v1.9.0 // indirect - golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect - golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f // indirect + golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa // indirect + golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect - golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34 // indirect - golang.org/x/text v0.3.6 // indirect + golang.org/x/sys v0.0.0-20211113001501-0c823b97ae02 // indirect + golang.org/x/text v0.3.7 // indirect + gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect ) diff --git a/core/src/foss/golang/go.sum b/core/src/foss/golang/go.sum index e620c8fa..ad7a146f 100644 --- a/core/src/foss/golang/go.sum +++ b/core/src/foss/golang/go.sum @@ -9,8 +9,9 @@ github.com/fanliao/go-promise v0.0.0-20141029170127-1890db352a72/go.mod h1:Pjfxu github.com/go-chi/chi/v5 v5.0.4/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-chi/cors v1.2.0/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58= github.com/go-chi/render v1.0.1/go.mod h1:pq4Rr7HbnsdaeHagklXub+p6Wd16Af5l9koip1OvJns= -github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gofrs/uuid v4.1.0+incompatible h1:sIa2eCvUTwgjbqXrPLfNwUf9S3i3mpH1O1atV+iL/Wk= +github.com/gofrs/uuid v4.1.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -20,18 +21,22 @@ github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORR github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714/go.mod h1:2Goc3h8EklBH5mspfHFxBnEoURQCGzQQH1ga9Myjvis= -github.com/insomniacslk/dhcp v0.0.0-20210827173440-b95caade3eac h1:IO6EfdRnPhxgKOsk9DbewdtQZHKZKnGlW7QCUttvNys= github.com/insomniacslk/dhcp v0.0.0-20210827173440-b95caade3eac/go.mod h1:h+MxyHxRg9NH3terB1nfRIUaQEcI0XOVkdR9LNBlp8E= +github.com/insomniacslk/dhcp v0.0.0-20211026125128-ad197bcd36fd h1:jupbuQFZtwOBg/3EmK91/rGaYFkqCb9bwHOnwn7Cav0= +github.com/insomniacslk/dhcp v0.0.0-20211026125128-ad197bcd36fd/go.mod h1:h+MxyHxRg9NH3terB1nfRIUaQEcI0XOVkdR9LNBlp8E= github.com/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw= github.com/jsimonetti/rtnetlink v0.0.0-20200117123717-f846d4f6c1f4/go.mod h1:WGuG/smIU4J/54PblvSbh+xvCZmpJnFgr3ds6Z55XMQ= github.com/jsimonetti/rtnetlink v0.0.0-20201009170750-9c6f07d100c1/go.mod h1:hqoO/u39cqLeBLebZ8fWdE96O7FxrAsRYhnVOdgHxok= github.com/jsimonetti/rtnetlink v0.0.0-20201110080708-d2c240429e6c/go.mod h1:huN4d1phzjhlOsNIjFsw2SVRbwIHj3fJDMEU2SDPTmg= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr328/tun2socket v0.0.0-20211114060954-370f53a7d3d7 h1:ln3WnceaKthifUEYKWyiZmZfPH88FTKbOHrEfSCd3dk= +github.com/kr328/tun2socket v0.0.0-20211114060954-370f53a7d3d7/go.mod h1:4NsuTykBBcrx78C3WMzjkIMC2vJicF6nSQUm1alZqYM= github.com/kr328/tun2socket-lwip v0.0.0-20211011111457-aee61f59119e/go.mod h1:JFkXLCpLkNVvLMRkq3gexTlRHfzbqcP5HfFOoq5Mj+g= -github.com/kr328/tun2socket-lwip v0.0.0-20211015020707-5db8ce531486 h1:vr7UW621Q53YUKUlsXojehQ4dtKXwyzin0hjwegC7gw= -github.com/kr328/tun2socket-lwip v0.0.0-20211015020707-5db8ce531486/go.mod h1:JFkXLCpLkNVvLMRkq3gexTlRHfzbqcP5HfFOoq5Mj+g= -github.com/kr328/tun2socket-lwip v0.0.0-20211015022349-94b5374d46e5 h1:Hsz4nGstXCWTLjf3mFDytJ0u1HfbrOfvbWRfphsLvBg= -github.com/kr328/tun2socket-lwip v0.0.0-20211015022349-94b5374d46e5/go.mod h1:JFkXLCpLkNVvLMRkq3gexTlRHfzbqcP5HfFOoq5Mj+g= github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7/go.mod h1:U6ZQobyTjI/tJyq2HG+i/dfSoFUt8/aZCM+GKtmFk/Y= github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA= github.com/mdlayher/netlink v1.0.0/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M= @@ -57,8 +62,9 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/u-root/uio v0.0.0-20210528114334-82958018845c h1:BFvcl34IGnw8yvJi8hlqLFo9EshRInwWBs2M5fGWzQA= github.com/u-root/uio v0.0.0-20210528114334-82958018845c/go.mod h1:LpEX5FO/cB+WF4TYGY1V5qktpaZLkKkSegbr0V4eYXA= +github.com/u-root/uio v0.0.0-20210528151154-e40b768296a7 h1:XMAtQHwKjWHIRwg+8Nj/rzUomQY1q6cM3ncA0wP8GU4= +github.com/u-root/uio v0.0.0-20210528151154-e40b768296a7/go.mod h1:LpEX5FO/cB+WF4TYGY1V5qktpaZLkKkSegbr0V4eYXA= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= @@ -66,8 +72,9 @@ go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210317152858-513c2a44f670/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa h1:idItI2DDfCokpg0N51B2VtiLdJ4vAuXC9fnCb2gACo4= +golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190419010253-1f3472d942ba/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -78,8 +85,9 @@ golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f h1:w6wWR0H+nyVpbSAQbzVEIACVyr/h8l/BEkY6Sokc7Eg= golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -102,18 +110,22 @@ golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34 h1:GkvMjFtXUmahfDtashnc1mnrCtuBVcwse5QV2lUk/tI= golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211110154304-99a53858aa08/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211113001501-0c823b97ae02 h1:7NCfEGl0sfUojmX78nK9pBJuUlSZWEJA/TwASvfiPLo= +golang.org/x/sys v0.0.0-20211113001501-0c823b97ae02/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= diff --git a/core/src/main/cpp/jni_helper.c b/core/src/main/cpp/jni_helper.c index c962b6dd..27140ab7 100644 --- a/core/src/main/cpp/jni_helper.c +++ b/core/src/main/cpp/jni_helper.c @@ -54,20 +54,27 @@ int jni_catch_exception(JNIEnv *env) { return result; } -void jni_attach_thread(JNIEnv **penv) { +void jni_attach_thread(struct _scoped_jni *jni) { JavaVM *vm = global_java_vm(); - if ((*vm)->AttachCurrentThread(vm, penv, NULL) != JNI_OK) { + if ((*vm)->GetEnv(vm, (void **) &jni->env, JNI_VERSION_1_6) == JNI_OK) { + jni->require_release = 0; + return; + } + + if ((*vm)->AttachCurrentThread(vm, &jni->env, NULL) != JNI_OK) { abort(); } + + jni->require_release = 1; } -void jni_detach_thread(JNIEnv **env) { - (void) env; - +void jni_detach_thread(struct _scoped_jni *jni) { JavaVM *vm = global_java_vm(); - (*vm)->DetachCurrentThread(vm); + if (jni->require_release) { + (*vm)->DetachCurrentThread(vm); + } } void release_string(char **str) { diff --git a/core/src/main/cpp/jni_helper.h b/core/src/main/cpp/jni_helper.h index 3c87107c..54156a89 100644 --- a/core/src/main/cpp/jni_helper.h +++ b/core/src/main/cpp/jni_helper.h @@ -6,21 +6,23 @@ #include #include +struct _scoped_jni { + JNIEnv *env; + int require_release; +}; + extern void initialize_jni(JavaVM *vm, JNIEnv *env); - extern jstring jni_new_string(JNIEnv *env, const char *str); - extern char *jni_get_string(JNIEnv *env, jstring str); - extern int jni_catch_exception(JNIEnv *env); - -extern void jni_attach_thread(JNIEnv **penv); - -extern void jni_detach_thread(JNIEnv **env); - +extern void jni_attach_thread(struct _scoped_jni *jni); +extern void jni_detach_thread(struct _scoped_jni *env); extern void release_string(char **str); -#define ATTACH_JNI() __attribute__((unused, cleanup(jni_detach_thread))) JNIEnv *env = NULL; jni_attach_thread(&env) +#define ATTACH_JNI() __attribute__((unused, cleanup(jni_detach_thread))) \ + struct _scoped_jni _jni; \ + jni_attach_thread(&_jni); \ + JNIEnv *env = _jni.env #define scoped_string __attribute__((cleanup(release_string))) char* diff --git a/core/src/main/cpp/main.c b/core/src/main/cpp/main.c index f1c632b0..1f8ae0c4 100644 --- a/core/src/main/cpp/main.c +++ b/core/src/main/cpp/main.c @@ -107,16 +107,19 @@ Java_com_github_kr328_clash_core_bridge_Bridge_nativeNotifyInstalledAppChanged(J JNIEXPORT void JNICALL Java_com_github_kr328_clash_core_bridge_Bridge_nativeStartTun(JNIEnv *env, jobject thiz, - jint fd, jint mtu, - jstring dns, jstring blocking, + jint fd, + jstring gateway, + jstring portal, + jstring dns, jobject cb) { TRACE_METHOD(); - scoped_string _blocking = get_string(blocking); + scoped_string _gateway = get_string(gateway); + scoped_string _portal = get_string(portal); scoped_string _dns = get_string(dns); jobject _interface = new_global(cb); - startTun(fd, mtu, _dns, _blocking, _interface); + startTun(fd, _gateway, _portal, _dns, _interface); } JNIEXPORT void JNICALL diff --git a/core/src/main/golang/native/config/defaults.go b/core/src/main/golang/native/config/defaults.go index 916c6431..41fb30df 100644 --- a/core/src/main/golang/native/config/defaults.go +++ b/core/src/main/golang/native/config/defaults.go @@ -7,10 +7,6 @@ var ( "8.8.8.8", "1.1.1.1", } - defaultFallback = []string{ - "https://1.1.1.1/dns-query", - "https://doh.pub/dns-query", - } defaultFakeIPFilter = []string{ // stun services "+.stun.*.*", @@ -24,8 +20,4 @@ var ( // Nintendo Switch "*.n.n.srv.nintendo.net", } - localNetwork = []string{ - "0.0.0.0/8", - "127.0.0.0/8", - } ) diff --git a/core/src/main/golang/native/config/process.go b/core/src/main/golang/native/config/process.go index 114d0cb9..782baca9 100644 --- a/core/src/main/golang/native/config/process.go +++ b/core/src/main/golang/native/config/process.go @@ -10,6 +10,7 @@ import ( "github.com/dlclark/regexp2" "cfa/native/common" + C "github.com/Dreamacro/clash/constant" "github.com/Dreamacro/clash/log" "github.com/Dreamacro/clash/config" @@ -54,6 +55,7 @@ func patchGeneral(cfg *config.RawConfig, _ string) error { func patchProfile(cfg *config.RawConfig, _ string) error { cfg.Profile.StoreSelected = false + cfg.Profile.StoreFakeIP = true return nil } @@ -63,11 +65,8 @@ func patchDns(cfg *config.RawConfig, _ string) error { cfg.DNS.Enable = true cfg.DNS.IPv6 = false cfg.DNS.NameServer = defaultNameServers - cfg.DNS.Fallback = defaultFallback - cfg.DNS.FallbackFilter.GeoIP = false - cfg.DNS.FallbackFilter.IPCIDR = localNetwork - cfg.DNS.EnhancedMode = dns.MAPPING - cfg.DNS.FakeIPRange = "198.18.0.0/16" + cfg.DNS.EnhancedMode = C.DNSFakeIP + cfg.DNS.FakeIPRange = "28.0.0.0/8" cfg.DNS.DefaultNameserver = defaultNameServers cfg.DNS.FakeIPFilter = defaultFakeIPFilter diff --git a/core/src/main/golang/native/tun.go b/core/src/main/golang/native/tun.go index 42d798ee..b09d6f65 100644 --- a/core/src/main/golang/native/tun.go +++ b/core/src/main/golang/native/tun.go @@ -5,6 +5,8 @@ import "C" import ( "context" + "io" + "sync" "unsafe" "golang.org/x/sync/semaphore" @@ -13,7 +15,11 @@ import ( "cfa/native/tun" ) +var rTunLock sync.Mutex +var rTun *remoteTun + type remoteTun struct { + closer io.Closer callback unsafe.Pointer closed bool @@ -21,7 +27,7 @@ type remoteTun struct { } func (t *remoteTun) markSocket(fd int) { - _ = t.limit.Acquire(context.TODO(), 1) + _ = t.limit.Acquire(context.Background(), 1) defer t.limit.Release(1) if t.closed { @@ -32,7 +38,7 @@ func (t *remoteTun) markSocket(fd int) { } func (t *remoteTun) querySocketUid(protocol int, source, target string) int { - _ = t.limit.Acquire(context.TODO(), 1) + _ = t.limit.Acquire(context.Background(), 1) defer t.limit.Release(1) if t.closed { @@ -42,38 +48,61 @@ func (t *remoteTun) querySocketUid(protocol int, source, target string) int { return int(C.query_socket_uid(t.callback, C.int(protocol), C.CString(source), C.CString(target))) } -func (t *remoteTun) stop() { - _ = t.limit.Acquire(context.Background(), 4) +func (t *remoteTun) close() { + _ = t.limit.Acquire(context.TODO(), 4) defer t.limit.Release(4) t.closed = true + if t.closer != nil { + _ = t.closer.Close() + } + app.ApplyTunContext(nil, nil) C.release_object(t.callback) } //export startTun -func startTun(fd, mtu C.int, gateway, dns C.c_string, callback unsafe.Pointer) C.int { +func startTun(fd C.int, gateway, portal, dns C.c_string, callback unsafe.Pointer) C.int { + rTunLock.Lock() + defer rTunLock.Unlock() + + if rTun != nil { + rTun.close() + rTun = nil + } + f := int(fd) - m := int(mtu) g := C.GoString(gateway) + p := C.GoString(portal) d := C.GoString(dns) remote := &remoteTun{callback: callback, closed: false, limit: semaphore.NewWeighted(4)} app.ApplyTunContext(remote.markSocket, remote.querySocketUid) - if tun.Start(f, m, g, d, remote.stop) != nil { - app.ApplyTunContext(nil, nil) + closer, err := tun.Start(f, g, p, d) + if err != nil { + remote.close() return 1 } + remote.closer = closer + + rTun = remote + return 0 } //export stopTun func stopTun() { - tun.Stop() + rTunLock.Lock() + defer rTunLock.Unlock() + + if rTun != nil { + rTun.close() + rTun = nil + } } diff --git a/core/src/main/golang/native/tun/link.go b/core/src/main/golang/native/tun/link.go deleted file mode 100644 index 5ca750e7..00000000 --- a/core/src/main/golang/native/tun/link.go +++ /dev/null @@ -1,39 +0,0 @@ -package tun - -import "github.com/Dreamacro/clash/log" - -func (a *adapter) rx() { - log.Infoln("[ATUN] Device rx started") - defer log.Infoln("[ATUN] Device rx exited") - defer a.once.Do(a.stop) - defer a.close() - - buf := make([]byte, a.mtu) - - for { - n, err := a.device.Read(buf) - if err != nil { - return - } - - _, _ = a.stack.Link().Write(buf[:n]) - } -} - -func (a *adapter) tx() { - log.Infoln("[ATUN] Device tx started") - defer log.Infoln("[ATUN] Device tx exited") - defer a.once.Do(a.stop) - defer a.close() - - buf := make([]byte, a.mtu) - - for { - n, err := a.stack.Link().Read(buf) - if err != nil { - return - } - - _, _ = a.device.Write(buf[:n]) - } -} diff --git a/core/src/main/golang/native/tun/tcp.go b/core/src/main/golang/native/tun/tcp.go deleted file mode 100644 index 1df0d2f0..00000000 --- a/core/src/main/golang/native/tun/tcp.go +++ /dev/null @@ -1,105 +0,0 @@ -package tun - -import ( - "encoding/binary" - "io" - "net" - "strconv" - "time" - - C "github.com/Dreamacro/clash/constant" - "github.com/Dreamacro/clash/context" - "github.com/Dreamacro/clash/log" - "github.com/Dreamacro/clash/tunnel" -) - -const defaultDnsReadTimeout = time.Second * 30 - -func (a *adapter) tcp() { - log.Infoln("[ATUN] TCP listener started") - defer log.Infoln("[ATUN] TCP listener exited") - defer a.stack.Close() - -accept: - for { - conn, err := a.stack.TCP().Accept() - if err != nil { - return - } - - sAddr := conn.LocalAddr().(*net.TCPAddr) - tAddr := conn.RemoteAddr().(*net.TCPAddr) - - // handle dns messages - if a.hijackTCPDNS(conn, tAddr) { - continue - } - - // drop all connections connect to blocking list - for _, b := range a.blocking { - if b.Contains(tAddr.IP) { - _ = conn.Close() - - continue accept - } - } - - metadata := &C.Metadata{ - NetWork: C.TCP, - Type: C.SOCKS5, - SrcIP: sAddr.IP, - DstIP: tAddr.IP, - SrcPort: strconv.Itoa(sAddr.Port), - DstPort: strconv.Itoa(tAddr.Port), - AddrType: C.AtypIPv4, - Host: "", - RawSrcAddr: sAddr, - RawDstAddr: tAddr, - } - - tunnel.TCPIn() <- context.NewConnContext(conn, metadata) - } -} - -func (a *adapter) hijackTCPDNS(conn net.Conn, tAddr *net.TCPAddr) bool { - if !shouldHijackDns(a.dns, tAddr.IP, tAddr.Port) { - return false - } - - go func() { - defer conn.Close() - - for { - if err := conn.SetReadDeadline(time.Now().Add(defaultDnsReadTimeout)); err != nil { - return - } - - var length uint16 - if binary.Read(conn, binary.BigEndian, &length) != nil { - return - } - - data := make([]byte, length) - - _, err := io.ReadFull(conn, data) - if err != nil { - return - } - - rb, err := relayDns(data) - if err != nil { - continue - } - - if binary.Write(conn, binary.BigEndian, uint16(len(rb))) != nil { - return - } - - if _, err := conn.Write(rb); err != nil { - return - } - } - }() - - return true -} diff --git a/core/src/main/golang/native/tun/tun.go b/core/src/main/golang/native/tun/tun.go index c6cef1ec..f3dc82c6 100644 --- a/core/src/main/golang/native/tun/tun.go +++ b/core/src/main/golang/native/tun/tun.go @@ -1,91 +1,168 @@ package tun import ( + "encoding/binary" + "io" "net" "os" - "strings" - "sync" - "syscall" + "strconv" + "time" - "github.com/kr328/tun2socket-lwip" + "github.com/kr328/tun2socket" + + "github.com/Dreamacro/clash/adapter/inbound" + "github.com/Dreamacro/clash/common/pool" + C "github.com/Dreamacro/clash/constant" + "github.com/Dreamacro/clash/context" + "github.com/Dreamacro/clash/log" + "github.com/Dreamacro/clash/transport/socks5" + "github.com/Dreamacro/clash/tunnel" ) -type adapter struct { - device *os.File - stack tun2socket.Stack - blocking []*net.IPNet - dns net.IP - mtu int - once sync.Once - stop func() -} +var _, ipv4LoopBack, _ = net.ParseCIDR("127.0.0.0/8") -var lock sync.Mutex -var instance *adapter - -func (a *adapter) close() { - _ = a.stack.Close() - _ = a.device.Close() -} - -func Start(fd, mtu int, dns string, blocking string, stop func()) error { - lock.Lock() - defer lock.Unlock() - - if instance != nil { - instance.close() - } - - _ = syscall.SetNonblock(fd, true) +func Start(fd int, gateway, portal, dns string) (io.Closer, error) { + log.Debugln("TUN: fd = %d, gateway = %s, portal = %s, dns = %s", fd, gateway, portal, dns) device := os.NewFile(uintptr(fd), "/dev/tun") - stack, err := tun2socket.NewStack(mtu) + stack, err := tun2socket.StartTun2Socket(device, net.ParseIP(gateway), net.ParseIP(portal)) if err != nil { _ = device.Close() - return err + return nil, err } - dn := net.ParseIP(dns) + dnsAddr := net.ParseIP(dns) - var blk []*net.IPNet + tcp := func() { + defer stack.TCP().Close() + defer log.Debugln("TCP: closed") - for _, b := range strings.Split(blocking, ";") { - _, n, err := net.ParseCIDR(b) - if err != nil { - device.Close() + for stack.TCP().SetDeadline(time.Time{}) == nil { + conn, err := stack.TCP().Accept() + if err != nil { + log.Debugln("Accept connection: %v", err) - return err + continue + } + + lAddr := conn.RemoteAddr().(*net.TCPAddr) + rAddr := conn.RemoteAddr().(*net.TCPAddr) + + if ipv4LoopBack.Contains(rAddr.IP) { + conn.Close() + + continue + } + + if shouldHijackDns(dnsAddr, rAddr.IP, rAddr.Port) { + go func() { + defer conn.Close() + + buf := pool.Get(pool.UDPBufferSize) + defer pool.Put(buf) + + for { + conn.SetReadDeadline(time.Now().Add(C.DefaultTCPTimeout)) + + length := uint16(0) + if err := binary.Read(conn, binary.BigEndian, &length); err != nil { + return + } + + if int(length) > len(buf) { + return + } + + n, err := conn.Read(buf[:length]) + if err != nil { + return + } + + msg, err := relayDns(buf[:n]) + if err != nil { + return + } + + _, _ = conn.Write(msg) + } + }() + + continue + } + + metadata := &C.Metadata{ + NetWork: C.TCP, + Type: C.SOCKS5, + SrcIP: lAddr.IP, + DstIP: rAddr.IP, + SrcPort: strconv.Itoa(lAddr.Port), + DstPort: strconv.Itoa(rAddr.Port), + AddrType: C.AtypIPv4, + Host: "", + RawSrcAddr: lAddr, + RawDstAddr: rAddr, + } + + tunnel.TCPIn() <- context.NewConnContext(conn, metadata) } - - blk = append(blk, n) } - instance = &adapter{ - device: device, - stack: stack, - blocking: blk, - dns: dn, - mtu: mtu, - once: sync.Once{}, - stop: stop, + udp := func() { + defer stack.UDP().Close() + defer log.Debugln("UDP: closed") + + for { + buf := pool.Get(pool.UDPBufferSize) + + n, lRAddr, rRAddr, err := stack.UDP().ReadFrom(buf) + if err != nil { + return + } + + raw := buf[:n] + lAddr := lRAddr.(*net.UDPAddr) + rAddr := rRAddr.(*net.UDPAddr) + + if ipv4LoopBack.Contains(rAddr.IP) { + pool.Put(buf) + + continue + } + + if shouldHijackDns(dnsAddr, rAddr.IP, rAddr.Port) { + go func() { + defer pool.Put(buf) + + msg, err := relayDns(raw) + if err != nil { + return + } + + _, _ = stack.UDP().WriteTo(msg, rAddr, lAddr) + }() + + continue + } + + pkt := &packet{ + local: lAddr, + data: raw, + writeBack: func(b []byte, addr net.Addr) (int, error) { + return stack.UDP().WriteTo(b, addr, lAddr) + }, + drop: func() { + pool.Put(buf) + }, + } + + tunnel.UDPIn() <- inbound.NewPacket(socks5.ParseAddrToSocksAddr(rAddr), pkt, C.SOCKS5) + } } - go instance.rx() - go instance.tx() - go instance.tcp() - go instance.udp() + go tcp() + go udp() + go udp() - return nil -} - -func Stop() { - lock.Lock() - defer lock.Unlock() - - if instance != nil { - instance.close() - } - - instance = nil + return stack, nil } diff --git a/core/src/main/golang/native/tun/udp.go b/core/src/main/golang/native/tun/udp.go index 0389447d..386bca8d 100644 --- a/core/src/main/golang/native/tun/udp.go +++ b/core/src/main/golang/native/tun/udp.go @@ -2,21 +2,13 @@ package tun import ( "net" - - "github.com/Dreamacro/clash/adapter/inbound" - "github.com/Dreamacro/clash/common/pool" - C "github.com/Dreamacro/clash/constant" - "github.com/Dreamacro/clash/log" - "github.com/Dreamacro/clash/transport/socks5" - "github.com/Dreamacro/clash/tunnel" - - "github.com/kr328/tun2socket-lwip" ) type packet struct { - stack tun2socket.Stack - local *net.UDPAddr - data []byte + local *net.UDPAddr + data []byte + writeBack func(b []byte, addr net.Addr) (int, error) + drop func() } func (pkt *packet) Data() []byte { @@ -24,76 +16,13 @@ func (pkt *packet) Data() []byte { } func (pkt *packet) WriteBack(b []byte, addr net.Addr) (n int, err error) { - return pkt.stack.UDP().WriteTo(b, pkt.local, addr) + return pkt.writeBack(b, addr) } func (pkt *packet) Drop() { - pool.Put(pkt.data) + pkt.drop() } func (pkt *packet) LocalAddr() net.Addr { - return &net.UDPAddr{ - IP: pkt.local.IP, - Port: pkt.local.Port, - Zone: "", - } -} - -func (a *adapter) udp() { - log.Infoln("[ATUN] UDP receiver started") - defer log.Infoln("[ATUN] UDP receiver exited") - defer a.stack.Close() - -read: - for { - buf := pool.Get(a.mtu) - - n, lAddr, rAddr, err := a.stack.UDP().ReadFrom(buf) - if err != nil { - return - } - - sAddr := lAddr.(*net.UDPAddr) - tAddr := rAddr.(*net.UDPAddr) - - // handle dns messages - if a.hijackUDPDNS(buf[:n], sAddr, tAddr) { - continue - } - - // drop all packet send to blocking list - for _, b := range a.blocking { - if b.Contains(tAddr.IP) { - continue read - } - } - - pkt := &packet{ - stack: a.stack, - local: sAddr, - data: buf[:n], - } - - tunnel.UDPIn() <- inbound.NewPacket(socks5.ParseAddrToSocksAddr(tAddr), pkt, C.SOCKS5) - } -} - -func (a *adapter) hijackUDPDNS(pkt []byte, sAddr, tAddr *net.UDPAddr) bool { - if !shouldHijackDns(a.dns, tAddr.IP, tAddr.Port) { - return false - } - - go func() { - answer, err := relayDns(pkt) - - if err != nil { - return - } - - _, _ = a.stack.UDP().WriteTo(answer, sAddr, tAddr) - - pool.Put(pkt) - }() - - return true + return pkt.local } diff --git a/core/src/main/java/com/github/kr328/clash/core/Clash.kt b/core/src/main/java/com/github/kr328/clash/core/Clash.kt index 3b2d5bb8..10ef45d3 100644 --- a/core/src/main/java/com/github/kr328/clash/core/Clash.kt +++ b/core/src/main/java/com/github/kr328/clash/core/Clash.kt @@ -64,13 +64,13 @@ object Clash { fun startTun( fd: Int, - mtu: Int, + gateway: String, + portal: String, dns: String, - blocking: String, markSocket: (Int) -> Boolean, querySocketUid: (protocol: Int, source: InetSocketAddress, target: InetSocketAddress) -> Int ) { - Bridge.nativeStartTun(fd, mtu, dns, blocking, object : TunInterface { + Bridge.nativeStartTun(fd, gateway, portal, dns, object : TunInterface { override fun markSocket(fd: Int) { markSocket(fd) } diff --git a/core/src/main/java/com/github/kr328/clash/core/bridge/Bridge.kt b/core/src/main/java/com/github/kr328/clash/core/bridge/Bridge.kt index b77588a3..7006ea5f 100644 --- a/core/src/main/java/com/github/kr328/clash/core/bridge/Bridge.kt +++ b/core/src/main/java/com/github/kr328/clash/core/bridge/Bridge.kt @@ -4,6 +4,7 @@ import android.os.Build import android.os.ParcelFileDescriptor import androidx.annotation.Keep import com.github.kr328.clash.common.Global +import com.github.kr328.clash.common.log.Log import kotlinx.coroutines.CompletableDeferred import java.io.File @@ -18,7 +19,7 @@ object Bridge { external fun nativeNotifyDnsChanged(dnsList: String) external fun nativeNotifyTimeZoneChanged(name: String, offset: Int) external fun nativeNotifyInstalledAppChanged(uidList: String) - external fun nativeStartTun(fd: Int, mtu: Int, dns: String, blocking: String, cb: TunInterface) + external fun nativeStartTun(fd: Int, gateway: String, portal: String, dns: String, cb: TunInterface) external fun nativeStopTun() external fun nativeStartHttp(listenAt: String): String? external fun nativeStopHttp() @@ -63,6 +64,8 @@ object Bridge { val versionName = ctx.packageManager.getPackageInfo(ctx.packageName, 0).versionName val sdkVersion = Build.VERSION.SDK_INT + Log.d("Home = $home") + nativeInit(home, versionName, sdkVersion) } } \ No newline at end of file diff --git a/service/src/main/java/com/github/kr328/clash/service/TunService.kt b/service/src/main/java/com/github/kr328/clash/service/TunService.kt index eef0c4ab..7b3345e5 100644 --- a/service/src/main/java/com/github/kr328/clash/service/TunService.kt +++ b/service/src/main/java/com/github/kr328/clash/service/TunService.kt @@ -207,8 +207,8 @@ class TunService : VpnService(), CoroutineScope by CoroutineScope(Dispatchers.De TunModule.TunDevice( fd = establish()?.detachFd() ?: throw NullPointerException("Establish VPN rejected by system"), - mtu = TUN_MTU, - blocking = blocking.joinToString(";"), + gateway = TUN_GATEWAY, + portal = TUN_PORTAL, dns = if (store.dnsHijacking) NET_ANY else TUN_DNS, ) } @@ -220,7 +220,8 @@ class TunService : VpnService(), CoroutineScope by CoroutineScope(Dispatchers.De private const val TUN_MTU = 9000 private const val TUN_SUBNET_PREFIX = 30 private const val TUN_GATEWAY = "172.19.0.1" - private const val TUN_DNS = "172.19.0.2" + private const val TUN_PORTAL = "172.19.0.2" + private const val TUN_DNS = TUN_PORTAL private const val NET_ANY = "0.0.0.0" private const val NET_SUBNET_LOOPBACK = "127.0.0.0/8" diff --git a/service/src/main/java/com/github/kr328/clash/service/clash/module/TunModule.kt b/service/src/main/java/com/github/kr328/clash/service/clash/module/TunModule.kt index 54944ee0..2be2413f 100644 --- a/service/src/main/java/com/github/kr328/clash/service/clash/module/TunModule.kt +++ b/service/src/main/java/com/github/kr328/clash/service/clash/module/TunModule.kt @@ -15,8 +15,8 @@ import java.security.SecureRandom class TunModule(private val vpn: VpnService) : Module(vpn) { data class TunDevice( val fd: Int, - val mtu: Int, - val blocking: String, + val gateway: String, + val portal: String, val dns: String, ) @@ -56,9 +56,9 @@ class TunModule(private val vpn: VpnService) : Module(vpn) { fun attach(device: TunDevice) { Clash.startTun( fd = device.fd, - mtu = device.mtu, + gateway = device.gateway, + portal = device.portal, dns = device.dns, - blocking = device.blocking, markSocket = vpn::protect, querySocketUid = this::queryUid )