-
Notifications
You must be signed in to change notification settings - Fork 63
[client] Add IPv6 dual-stack support #148
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
base: main
Are you sure you want to change the base?
Changes from all commits
3f573e8
297b618
090b6a0
2f4abec
bce03cb
7465104
70eb8be
8f3adec
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -28,22 +28,26 @@ public IFace(VPNService vpnService) { | |
| } | ||
|
|
||
| @Override | ||
| public long configureInterface(String address, long mtu, String dns, String searchDomainsString, String routesString) throws Exception { | ||
| public long configureInterface(String address, String addressV6, long mtu, String dns, String searchDomainsString, String routesString) throws Exception { | ||
| String[] searchDomains = toSearchDomains(searchDomainsString); | ||
| LinkedList<Route> routes = toRoutes(routesString); | ||
|
|
||
| InetNetwork addr = InetNetwork.parse(address); | ||
| InetNetwork addrV6 = null; | ||
| if (addressV6 != null && !addressV6.isEmpty()) { | ||
| addrV6 = InetNetwork.parse(addressV6); | ||
| } | ||
| long fd = -1; | ||
|
|
||
| try { | ||
| fd = createTun(addr.getAddress().getHostAddress(), addr.getMask(), (int) mtu, dns, searchDomains, routes); | ||
| fd = createTun(addr.getAddress().getHostAddress(), addr.getMask(), addrV6, (int) mtu, dns, searchDomains, routes); | ||
| } catch (Exception e) { | ||
| Log.e(LOGTAG, "failed to create tunnel", e); | ||
| } | ||
|
|
||
| // only set the currently used TUN parameters if createTun didn't throw exceptions | ||
| if (fd != -1) { | ||
| this.vpnService.setCurrentTUNParameters(new TUNParameters(address, mtu, dns, searchDomainsString, routesString)); | ||
| this.vpnService.setCurrentTUNParameters(new TUNParameters(address, addressV6, mtu, dns, searchDomainsString, routesString)); | ||
| } | ||
|
|
||
| return fd; | ||
|
|
@@ -57,9 +61,13 @@ public boolean protectSocket(int fd) { | |
| return true; | ||
| } | ||
|
|
||
| private int createTun(String ip, int prefixLength, int mtu, String dns, String[] searchDomains, LinkedList<Route> routes) throws Exception { | ||
| private int createTun(String ip, int prefixLength, InetNetwork addrV6, int mtu, String dns, String[] searchDomains, LinkedList<Route> routes) throws Exception { | ||
| VpnService.Builder builder = vpnService.getBuilder(); | ||
| builder.addAddress(ip, prefixLength); | ||
| if (addrV6 != null) { | ||
| builder.addAddress(addrV6.getAddress().getHostAddress(), addrV6.getMask()); | ||
| Log.d(LOGTAG, "add IPv6 address: " + addrV6.getAddress().getHostAddress() + "/" + addrV6.getMask()); | ||
| } | ||
| builder.allowFamily(OsConstants.AF_INET); | ||
| builder.allowFamily(OsConstants.AF_INET6); | ||
| builder.setMtu(mtu); | ||
|
|
@@ -69,6 +77,10 @@ private int createTun(String ip, int prefixLength, int mtu, String dns, String[] | |
| Log.d(LOGTAG,"add search domain: "+ sd); | ||
| } | ||
|
|
||
| if (addrV6 == null && hasIPv4DefaultRoute(routes)) { | ||
| routes.add(new Route("::/0")); | ||
| } | ||
|
Comment on lines
+80
to
+82
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: cat -n tool/src/main/java/io/netbird/client/tool/IFace.java | head -90Repository: netbirdio/android-client Length of output: 4092 🏁 Script executed: cat -n tool/src/main/java/io/netbird/client/tool/IFace.java | sed -n '60,180p'Repository: netbirdio/android-client Length of output: 5157 🏁 Script executed: fd -t f "Route\.java" --exec cat {} \;Repository: netbirdio/android-client Length of output: 396 Blackhole IPv6 based on missing The presence of an IPv6 interface address does not guarantee a Proposed fix- if (addrV6 == null && hasIPv4DefaultRoute(routes)) {
+ if (hasIPv4DefaultRoute(routes) && !hasIPv6DefaultRoute(routes)) {
routes.add(new Route("::/0"));
}- // Blackhole IPv6 when the tunnel has an IPv4 default route but no IPv6
- // address on the interface, to prevent IPv6 leaks around the tunnel.
+ // Blackhole IPv6 when the tunnel has an IPv4 default route but no IPv6
+ // default route, to prevent IPv6 leaks around the tunnel.
private boolean hasIPv4DefaultRoute(LinkedList<Route> routes) {
for (Route r : routes) {
if ("0.0.0.0".equals(r.addr) && r.prefixLength == 0) {
return true;
}
}
return false;
}
+
+ private boolean hasIPv6DefaultRoute(LinkedList<Route> routes) {
+ for (Route r : routes) {
+ if (r.addr != null && r.addr.contains(":") && r.prefixLength == 0) {
+ return true;
+ }
+ }
+ return false;
+ }🤖 Prompt for AI Agents
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the hasIpv6 case mgmt will send a proper non black hole route as well
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
✏️ Learnings added
|
||
|
|
||
| for (Route r : routes) { | ||
| builder.addRoute(r.addr, r.prefixLength); | ||
| Log.d(LOGTAG, "add route: "+r.addr+"/"+r.prefixLength); | ||
|
|
@@ -149,6 +161,17 @@ private String[] toSearchDomains(String searchDomains) { | |
| return searchDomains.split(";"); | ||
| } | ||
|
|
||
| // Blackhole IPv6 when the tunnel has an IPv4 default route but no IPv6 | ||
| // address on the interface, to prevent IPv6 leaks around the tunnel. | ||
| private boolean hasIPv4DefaultRoute(LinkedList<Route> routes) { | ||
| for (Route r : routes) { | ||
| if ("0.0.0.0".equals(r.addr) && r.prefixLength == 0) { | ||
| return true; | ||
| } | ||
| } | ||
| return false; | ||
| } | ||
|
|
||
| private LinkedList<Route> toRoutes(String routesString) { | ||
| LinkedList<Route> routesList = new LinkedList<>(); | ||
| if(routesString == null) { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.