Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use file descriptor in Android? #123

Closed
marco20240618 opened this issue Apr 30, 2022 · 17 comments
Closed

How to use file descriptor in Android? #123

marco20240618 opened this issue Apr 30, 2022 · 17 comments
Labels
documentation Improvements or additions to documentation

Comments

@marco20240618
Copy link

Description

Related to issue #71
Sorry to bother, I appended my quesiton to issuse #71 , but no response. so I opened a new issuse.

In badvpn(https://github.com/ambrop72/badvpn), I see this command
tun2socks --netif-ipaddr 26.26.26.2 --netif-netmask 255.255.255.0 --socks-server-addr 127.0.0.1:1080 --tunmtu 1500 --loglevel notice --enable-udprelay --sock-path /tmp/sock_path

and then send the file desriptor of the tun0 device to --sock-path

To be more specific, this is how badvpn-tun2socks works in Android.

  1. create a tun device
android.net.VpnService.Builder builder = new android.net.VpnService.Builder()
                    .setMtu(1500)
                    .addAddress("26.26.26.1", 24)
                    .addDnsServer("8.8.8.8")
                    .addRoute("0.0.0.0", 0);
mInterface = builder.establish();
  1. run tun2socks
String tun2socks_command = String.format(java.util.Locale.US, "%s/libtun2socks.so --netif-ipaddr 26.26.26.2 --netif-netmask 255.255.255.0 --socks-server-addr 127.0.0.1:1080 --tunmtu 1500 --loglevel notice --enable-udprelay --sock-path %s/sock_path", this.getApplicationInfo().nativeLibraryDir, this.getApplicationInfo().dataDir);
Runtime.getRuntime().exec(tun2socks_command);
  1. send file descriptor of tun0 to sock-path
            int tries = 0;
            while (true) {
                try {
                    Thread.sleep(1000L * tries);
                    android.net.LocalSocket ls = new android.net.LocalSocket();
                    ls.connect(new android.net.LocalSocketAddress(getApplicationInfo().dataDir + "/sock_path", android.net.LocalSocketAddress.Namespace.FILESYSTEM));
                    ls.setFileDescriptorsForSend(new java.io.FileDescriptor[]{mInterface.getFileDescriptor()});
                    ls.getOutputStream().write(42);
                    break;
                } catch (Exception e) {
                    if (tries > 5) {
                        break;
                    }
                    ++tries;
                    Util.myLog(this, "fd send error, tries: " + tries);
                }
            }

Is this feature related to a specific bug?

No response

Do you have a specific solution in mind?

No response

@tabjy
Copy link

tabjy commented May 3, 2022

I had success using gomobile bind to directly compile this project into an Android library (.aar). Therefore, sharing descriptor across processes is no longer required:

ParcelFileDescriptor tunDevice = new Builder()
    .addAddress(VPN_ADDRESS, 32)
    .addRoute(VPN_ROUTE, 0)
    .addDnsServer(VPN_DNS)
    .addAllowedApplication("com.google.android.tethering")
    .establish();

engine.Key key = new engine.Key();
key.setMark(0);
key.setMTU(0);
key.setDevice("fd://" + tunDevice.getFd()); // <--- here
key.setInterface("");
key.setLogLevel("debug");
key.setProxy("socks5://127.0.0.1:1080"); // <--- and here
key.setRestAPI("");
key.setTCPSendBufferSize("");
key.setTCPReceiveBufferSize("");
key.setTCPModerateReceiveBuffer(false);

engine.Engine.insert(key);
engine.Engine.start();

In my case, it was acceptable to use SOCKS5 over TCP as my VPN service is configured not routing packets from my own application. No loopback is going to happen. You probably gonna want to protect your SOCKS5 connections or use an Unix Domain Socket to your local SOCKS5 server:

key.setProxy("socks5:///path/to/unix/domain/socket");

@marco20240618
Copy link
Author

it worked. thanks. great project.

@yaem1k0
Copy link

yaem1k0 commented Jul 1, 2022

@tabjy Can you tell me how to build it? I want to use this library in my Android project, but i am totally inexperienced for Golang programming. I tried to build it use gomobile into tun2socks.aar many times but all failed.

@tabjy
Copy link

tabjy commented Jul 2, 2022

I understand this issue is closed, but for the sake of helping out @yaem1k0:

Make sure your ANDROID_HOME, ANDROID_NDK_HOME and GOPATH are set:

$ go install golang.org/x/mobile/cmd/gomobile@latest
$ go get golang.org/x/mobile/bind
$ gomobile init
$ go install github.com/xjasonlyu/tun2socks/v2@latest
$ export DEST=$(pwd)/app/libs
$ mkdir -p DEST
$ cd $GOPATH/src/github.com/xjasonlyu/tun2socks
$ gomobile bind -o $DEST/tun2socks.aar -target android $GOPATH/src/github.com/xjasonlyu/tun2socks/engine
$ ls $DEST # you should see tun2socks.aar and tun2socks-sources.jar

Add the following to your settings.gradle:

 dependencyResolutionManagement {
     repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
     repositories {
         google()
         mavenCentral()
+        flatDir {
+            dirs 'app/libs'
+        }
     }
 }

Add the dependency to your app/build.gradle:

 dependencies {
+    implementation (name:'tun2socks', ext:'aar')

     implementation 'androidx.core:core-ktx:1.7.0'
     // omitted...
}

Execute "Sync Project with Gradle Files" action in Android Studio. Then the engine package would be added to your build path:

import engine.Engine;

See my previous reply for usage. Note that it seemed necessary to set empty values even for unused options.

@yaem1k0
Copy link

yaem1k0 commented Jul 5, 2022

It worked, thanks a lot. @tabjy

@zmou
Copy link

zmou commented Jan 5, 2023

I had success using gomobile bind to directly compile this project into an Android library (.aar). Therefore, sharing descriptor across processes is no longer required:

ParcelFileDescriptor tunDevice = new Builder()
    .addAddress(VPN_ADDRESS, 32)
    .addRoute(VPN_ROUTE, 0)
    .addDnsServer(VPN_DNS)
    .addAllowedApplication("com.google.android.tethering")
    .establish();

engine.Key key = new engine.Key();
key.setMark(0);
key.setMTU(0);
key.setDevice("fd://" + tunDevice.getFd()); // <--- here
key.setInterface("");
key.setLogLevel("debug");
key.setProxy("socks5://127.0.0.1:1080"); // <--- and here
key.setRestAPI("");
key.setTCPSendBufferSize("");
key.setTCPReceiveBufferSize("");
key.setTCPModerateReceiveBuffer(false);

engine.Engine.insert(key);
engine.Engine.start();

In my case, it was acceptable to use SOCKS5 over TCP as my VPN service is configured not routing packets from my own application. No loopback is going to happen. You probably gonna want to protect your SOCKS5 connections or use an Unix Domain Socket to your local SOCKS5 server:

key.setProxy("socks5:///path/to/unix/domain/socket");

How to protect socket, thank you!

@ukhack
Copy link

ukhack commented Feb 6, 2023

I understand this issue is closed, but for the sake of helping out @yaem1k0:

Make sure your ANDROID_HOME, ANDROID_NDK_HOME and GOPATH are set:

$ go install golang.org/x/mobile/cmd/gomobile@latest
$ go get golang.org/x/mobile/bind
$ gomobile init
$ go install github.com/xjasonlyu/tun2socks/v2@latest
$ export DEST=$(pwd)/app/libs
$ mkdir -p DEST
$ cd $GOPATH/src/github.com/xjasonlyu/tun2socks
$ gomobile bind -o $DEST/tun2socks.aar -target android $GOPATH/src/github.com/xjasonlyu/tun2socks/engine
$ ls $DEST # you should see tun2socks.aar and tun2socks-sources.jar

Add the following to your settings.gradle:

 dependencyResolutionManagement {
     repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
     repositories {
         google()
         mavenCentral()
+        flatDir {
+            dirs 'app/libs'
+        }
     }
 }

Add the dependency to your app/build.gradle:

 dependencies {
+    implementation (name:'tun2socks', ext:'aar')

     implementation 'androidx.core:core-ktx:1.7.0'
     // omitted...
}

Execute "Sync Project with Gradle Files" action in Android Studio. Then the engine package would be added to your build path:

import engine.Engine;

See my previous reply for usage. Note that it seemed necessary to set empty values even for unused options.

On my device, dns request not through the Proxy。

@Ali-Khazaee
Copy link

Ali-Khazaee commented Mar 10, 2023

@tabjy Default libtun2socks.so size is approx 200KB for each arch, but your AAR version size is approx 11MB for each arch

why is that ?

I did build tun2socks and yes it's size is approx 9MB

@tabjy
Copy link

tabjy commented Mar 14, 2023

@Ali-Khazaee

but your AAR version size is approx 11MB for each arch

an AAR includes builds for all archs

Screenshot_2023-03-13-15-18-02_4880x3040

@saaam000
Copy link

How to handle UDP connections too ?

@sonvirgo
Copy link

sonvirgo commented Jul 29, 2023

In Android there is already some tun2socks app work flawless, with per app tun features. It mean loop-free with localhost 127.0.0.1 socks
For example SocksDroid

@bigfoxtail
Copy link

I had success using gomobile bind to directly compile this project into an Android library (.aar). Therefore, sharing descriptor across processes is no longer required:

ParcelFileDescriptor tunDevice = new Builder()
    .addAddress(VPN_ADDRESS, 32)
    .addRoute(VPN_ROUTE, 0)
    .addDnsServer(VPN_DNS)
    .addAllowedApplication("com.google.android.tethering")
    .establish();

engine.Key key = new engine.Key();
key.setMark(0);
key.setMTU(0);
key.setDevice("fd://" + tunDevice.getFd()); // <--- here
key.setInterface("");
key.setLogLevel("debug");
key.setProxy("socks5://127.0.0.1:1080"); // <--- and here
key.setRestAPI("");
key.setTCPSendBufferSize("");
key.setTCPReceiveBufferSize("");
key.setTCPModerateReceiveBuffer(false);

engine.Engine.insert(key);
engine.Engine.start();

In my case, it was acceptable to use SOCKS5 over TCP as my VPN service is configured not routing packets from my own application. No loopback is going to happen. You probably gonna want to protect your SOCKS5 connections or use an Unix Domain Socket to your local SOCKS5 server:

key.setProxy("socks5:///path/to/unix/domain/socket");

How can I use engine.Engine.start(); engine.Engine.stop(); in an Android VPN application to start and stop tun2socks? Sorry, I'm a beginner and not quite sure.
Thanks😀

@ys1231
Copy link

ys1231 commented May 25, 2024

Develop according to the above, the log shows connect: connection refused ,I need help
Trying to use other proxy software to connect is successful and no password is required.
image
image

@anasfanani
Copy link

This is not for file descriptor, while read documentation and click on Android section is show me this issue.

Use tun2socks all internet except dns with root.

# id
uid=0(root) gid=0(root) groups=0(root) context=u:r:magisk:s0

Create interface

ip tuntap add mode tun dev tun0
ip addr add 198.18.0.1/15 dev tun0
ip link set dev tun0 up

Socks server: 72.210.221.197:4145 .
Create iptables rule

iptables -t mangle -N TUNSOCKS 2>/dev/null
iptables -t mangle -F TUNSOCKS
iptables -t mangle -I OUTPUT -j TUNSOCKS
iptables -t mangle -I TUNSOCKS -p tcp -d 72.210.221.197 --dport 4145 -j RETURN
# iptables -t mangle -I TUNSOCKS -m owner --uid-owner "root" --gid-owner "net_bt_admin" -j RETURN
iptables -t mangle -I TUNSOCKS -p udp --dport 53 -j RETURN
iptables -t mangle -A TUNSOCKS -j MARK --set-mark 1337
ip route add default dev tun0 table 21 metric 1
ip rule add fwmark 1337 lookup 21 pref 10

Run program

./tun2socks-linux-arm64 -device tun0 -proxy socks5://72.210.221.197:4145 -loglevel debug 

Revert back / delete iptables route

# del route
iptables -t mangle -F TUNSOCKS
iptables -t mangle -D OUTPUT -j TUNSOCKS
iptables -t mangle -X TUNSOCKS
ip route del default dev tun0 table 21 metric 1
ip rule del fwmark 1337 lookup 21 pref 10
# del interface
ip addr del 198.18.0.1/15 dev tun0
ip link set dev tun0 down
ip tuntap del mode tun dev tun0

If the server running local, run server program with

busybox setuidgid "root:net_bt_admin" ./socks-server

Use this to bypass server traffict

iptables -t mangle -I TUNSOCKS -m owner --uid-owner "root" --gid-owner "net_bt_admin" -j RETURN

@misa3l
Copy link

misa3l commented Jun 6, 2024

Is there a way to get the Tx and Rx of the connection established with the Socks5 server? Is there a method to obtain these connection statistics?

@xjasonlyu
Copy link
Owner

yea, you can use the rest api in tun2socks

@redwind
Copy link

redwind commented Sep 15, 2024

I using this for my proxy app but got
[UDP] dial 1.1.1.1:53: unsupported operation
with UDP DNS query.
Anyone faced this issue ?
Thank you !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests