From ac86caaf8b8fc743a1dfa6721b759ad2f9a0859c Mon Sep 17 00:00:00 2001 From: amurcanov Date: Sat, 23 May 2026 22:18:08 +0300 Subject: [PATCH] Initial v1.1.8 Commits --- .gitignore | 53 + LICENSE | 674 +++++++ README.md | 158 ++ app/build.gradle.kts | 143 ++ app/proguard-rules.pro | 4 + app/src/main/AndroidManifest.xml | 57 + app/src/main/assets/deploy.sh | 585 ++++++ app/src/main/ic_launcher-playstore.png | Bin 0 -> 334012 bytes .../main/java/com/wdtt/client/AppUpdate.kt | 276 +++ .../com/wdtt/client/CaptchaWebViewManager.kt | 599 ++++++ .../java/com/wdtt/client/DeployManager.kt | 88 + .../main/java/com/wdtt/client/MainActivity.kt | 671 +++++++ .../wdtt/client/ManlCaptchaWebViewManager.kt | 388 ++++ .../java/com/wdtt/client/SecureStringStore.kt | 72 + .../java/com/wdtt/client/SettingsStore.kt | 393 ++++ app/src/main/java/com/wdtt/client/Theme.kt | 281 +++ .../java/com/wdtt/client/TunnelManager.kt | 836 ++++++++ .../java/com/wdtt/client/TunnelService.kt | 378 ++++ .../com/wdtt/client/UserAgentGenerator.kt | 77 + .../java/com/wdtt/client/WdttApplication.kt | 24 + .../java/com/wdtt/client/WireGuardHelper.kt | 209 ++ .../java/com/wdtt/client/ui/AppSectionCard.kt | 66 + .../com/wdtt/client/ui/AppUpdateDialog.kt | 128 ++ .../main/java/com/wdtt/client/ui/DeployTab.kt | 912 +++++++++ .../java/com/wdtt/client/ui/ExceptionsTab.kt | 297 +++ .../com/wdtt/client/ui/FloatingToolbar.kt | 305 +++ .../main/java/com/wdtt/client/ui/InfoTab.kt | 902 +++++++++ .../main/java/com/wdtt/client/ui/LogsTab.kt | 147 ++ .../java/com/wdtt/client/ui/SettingsTab.kt | 1099 +++++++++++ app/src/main/res/drawable/ic_da.xml | 22 + app/src/main/res/drawable/ic_da_black.xml | 10 + app/src/main/res/drawable/ic_github.xml | 9 + .../main/res/drawable/ic_stat_connected.xml | 9 + app/src/main/res/drawable/ic_stop.xml | 9 + app/src/main/res/drawable/ic_yoomoney.xml | 25 + .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 + .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 + app/src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 10608 bytes .../mipmap-hdpi/ic_launcher_foreground.png | Bin 0 -> 334012 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 9843 bytes app/src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 5270 bytes .../mipmap-mdpi/ic_launcher_foreground.png | Bin 0 -> 334012 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 5028 bytes app/src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 17648 bytes .../mipmap-xhdpi/ic_launcher_foreground.png | Bin 0 -> 334012 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 16235 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 36602 bytes .../mipmap-xxhdpi/ic_launcher_foreground.png | Bin 0 -> 334012 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 32879 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 59998 bytes .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 0 -> 334012 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 53310 bytes app/src/main/res/values/colors.xml | 4 + app/src/main/res/values/themes.xml | 7 + build.gradle.kts | 4 + go.mod | 23 + go_client/captcha_v2.go | 655 +++++++ go_client/captcha_v2_slider.go | 637 ++++++ go_client/creds.go | 675 +++++++ go_client/dispatcher.go | 198 ++ go_client/go.mod | 33 + go_client/group.go | 300 +++ go_client/main.go | 305 +++ go_client/namegen.go | 74 + go_client/obfs.go | 208 ++ go_client/profiles.go | 114 ++ go_client/protocol.go | 49 + go_client/session.go | 424 ++++ go_client/stats.go | 38 + go_client/wrap.go | 33 + gradle.properties | 3 + gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 43504 bytes gradle/wrapper/gradle-wrapper.properties | 7 + gradlew | 252 +++ server.go | 1718 +++++++++++++++++ settings.gradle.kts | 16 + 76 files changed, 15693 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 app/build.gradle.kts create mode 100644 app/proguard-rules.pro create mode 100644 app/src/main/AndroidManifest.xml create mode 100644 app/src/main/assets/deploy.sh create mode 100644 app/src/main/ic_launcher-playstore.png create mode 100644 app/src/main/java/com/wdtt/client/AppUpdate.kt create mode 100644 app/src/main/java/com/wdtt/client/CaptchaWebViewManager.kt create mode 100644 app/src/main/java/com/wdtt/client/DeployManager.kt create mode 100644 app/src/main/java/com/wdtt/client/MainActivity.kt create mode 100644 app/src/main/java/com/wdtt/client/ManlCaptchaWebViewManager.kt create mode 100644 app/src/main/java/com/wdtt/client/SecureStringStore.kt create mode 100644 app/src/main/java/com/wdtt/client/SettingsStore.kt create mode 100644 app/src/main/java/com/wdtt/client/Theme.kt create mode 100644 app/src/main/java/com/wdtt/client/TunnelManager.kt create mode 100644 app/src/main/java/com/wdtt/client/TunnelService.kt create mode 100644 app/src/main/java/com/wdtt/client/UserAgentGenerator.kt create mode 100644 app/src/main/java/com/wdtt/client/WdttApplication.kt create mode 100644 app/src/main/java/com/wdtt/client/WireGuardHelper.kt create mode 100644 app/src/main/java/com/wdtt/client/ui/AppSectionCard.kt create mode 100644 app/src/main/java/com/wdtt/client/ui/AppUpdateDialog.kt create mode 100644 app/src/main/java/com/wdtt/client/ui/DeployTab.kt create mode 100644 app/src/main/java/com/wdtt/client/ui/ExceptionsTab.kt create mode 100644 app/src/main/java/com/wdtt/client/ui/FloatingToolbar.kt create mode 100644 app/src/main/java/com/wdtt/client/ui/InfoTab.kt create mode 100644 app/src/main/java/com/wdtt/client/ui/LogsTab.kt create mode 100644 app/src/main/java/com/wdtt/client/ui/SettingsTab.kt create mode 100644 app/src/main/res/drawable/ic_da.xml create mode 100644 app/src/main/res/drawable/ic_da_black.xml create mode 100644 app/src/main/res/drawable/ic_github.xml create mode 100644 app/src/main/res/drawable/ic_stat_connected.xml create mode 100644 app/src/main/res/drawable/ic_stop.xml create mode 100644 app/src/main/res/drawable/ic_yoomoney.xml create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/values/colors.xml create mode 100644 app/src/main/res/values/themes.xml create mode 100644 build.gradle.kts create mode 100644 go.mod create mode 100644 go_client/captcha_v2.go create mode 100644 go_client/captcha_v2_slider.go create mode 100644 go_client/creds.go create mode 100644 go_client/dispatcher.go create mode 100644 go_client/go.mod create mode 100644 go_client/group.go create mode 100644 go_client/main.go create mode 100644 go_client/namegen.go create mode 100644 go_client/obfs.go create mode 100644 go_client/profiles.go create mode 100644 go_client/protocol.go create mode 100644 go_client/session.go create mode 100644 go_client/stats.go create mode 100644 go_client/wrap.go create mode 100644 gradle.properties create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew create mode 100644 server.go create mode 100644 settings.gradle.kts diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..396b850 --- /dev/null +++ b/.gitignore @@ -0,0 +1,53 @@ +# ===== Gradle ===== +.gradle/ +build/ +local.properties + +# ===== Android ===== +*.apk +*.aab +*.ap_ +*.dex +*.class +app/build/ +app/release/ + +# ===== Go ===== +go.sum + +# ===== Native Libraries (compiled) ===== +*.so +*.dll +*.dylib +jniLibs/ +app/src/main/jniLibs/ + +# ===== Server binary ===== +app/src/main/assets/server +server + +# ===== Keystore / Secrets ===== +*.keystore +*.jks +*.key +*.pem + +# ===== IDE ===== +.idea/ +*.iml +.vscode/ +*.swp +*.swo +*~ + +# ===== OS ===== +.DS_Store +Thumbs.db +Desktop.ini + +# ===== Misc ===== +*.log +*.tmp +*.bak +msg.txt +*.bat diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f288702 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/README.md b/README.md new file mode 100644 index 0000000..c23c466 --- /dev/null +++ b/README.md @@ -0,0 +1,158 @@ +
+ + # WDTT — WireGuard over TURN Tunnel +
+ Android SDK + Go Version + Kotlin + + Stars + +
+
+ +**WDTT** — это Android-приложение для создания защищённого **WireGuard-туннеля поверх TURN/DTLS**. Клиент поднимает локальный VPN-интерфейс на устройстве, получает WireGuard-конфигурацию от вашего VPS и передаёт транспорт через TURN-серверы VK, маскируя соединение под обычный зашифрованный медиатрафик звонка. + +--- + +MyCollages (2) + +## Возможности Android-версии + +- **Полноценный VPN-режим:** приложение использует `VpnService` и WireGuard GoBackend, поэтому трафик выбранных приложений проходит через системный VPN-интерфейс без ручного импорта конфигов. +- **TURN/DTLS-транспорт:** нативный Go-клиент получает временные TURN-учётные данные VK-звонка и поднимает DTLS-соединения к relay-серверу, через который передаётся трафик до вашего VPS. +- **Деплой с телефона:** вкладка **«Деплой»** подключается к серверу по SSH, загружает `wdtt-server`, создаёт `systemd`-сервис, включает NAT/firewall и открывает рабочие UDP-порты. +- **Парольная модель доступа:** сервер поддерживает главный пароль, одноразовые/срочные пароли, привязку пароля к устройству и управление через Telegram-бота. +- **Исключения приложений:** можно выбрать, какие приложения идут через туннель, а какие работают напрямую. Поддерживаются режимы ЧС и БС, а изменения применяются перезагрузкой WireGuard без полного перенастраивания. +- **Капча VK Smart Captcha:** основной рабочий режим в текущей Android-сборке — `WBV/WebView` с ручным решением или автоматической попыткой для простых сценариев. RJS-логика есть в Go-ядре, но в UI текущей сборки временно отключена. +- **Живой лог-вьюер:** события Go-клиента, DTLS, WireGuard, капчи, деплоя и статистики отображаются в приложении с группировкой одинаковых сообщений и счётчиками повторов. +- **Фоновая устойчивость:** `Foreground Service`, `WakeLock`, `WifiLock`, мониторинг смены сети и watchdog помогают переживать Doze, смену Wi-Fi/LTE и падение нативного процесса. +- **Темы и оформление:** Material 3, Jetpack Compose, Inter, светлая/тёмная тема, Dynamic Colors на Android 12+ и встроенные палитры. +- **Автообновления:** приложение проверяет GitHub releases, показывает диалог обновления и позволяет перейти на страницу актуального релиза. + +## Что нового в версии 1.1.0 + +> [!IMPORTANT] +> После обновления до **1.1.0** необходимо заново выполнить **деплой сервера** из приложения. + +* **Изоляция WDTT:** деплой, удаление и рабочая среда **WDTT** теперь не должны влиять на другие компоненты VPS. Серверная часть изолирована в собственной конфигурации, интерфейсе и правилах firewall/NAT. +* **Автообновление:** помимо ручной проверки, приложение теперь самостоятельно проверяет наличие новых версий и предлагает обновиться до актуального релиза. +* **Ручные порты:** добавлена возможность управлять портами. При включении режима ручных портов можно задать **DTLS** и **WG** порты на сервере, а также локальный VPN-порт в туннеле. Если это не нужно, режим лучше не включать. +* **Капча:** возвращён режим **Авто-WBV** для прохождения капчи **«Я не робот»**. Режим **RJS** временно заблокирован до следующих улучшений. Если с **Авто-WBV** возникают проблемы, используйте ручной режим. +* **Разделение архитектур:** релизы теперь делятся на **arm64-v8a**, **armeabi-v7a** и **x86_64**, чтобы уменьшить размер APK. Если вы не знаете, какой APK выбрать, используйте **Universal** — он содержит все 3 архитектуры, но весит больше. +* **Сборка:** обновлены **AGP**, **Gradle** и **Kotlin** до актуальных версий (`9.0.1`, `9.1.0`, `2.x`), что положительно влияет на стабильность и работу приложения. +* **Багфиксы и стабильность:** удалён **DataSync**, который мог вызывать краши на **Android 14+**; изменено поведение уведомления, чтобы оно не скакало в шторке; улучшен запуск **VPN Service** и передача WireGuard-конфига. +* **Интерфейс и информация:** проведён небольшой редизайн, добавлены тени и орбы на фон. Раздел **«Инфо»** переработан и теперь позволяет собрать отчёт с данными об устройстве для более точного разбора ошибок. +* **В планах:** заменить стандартный протокол **WireGuard** на **AmneziaWG** в версиях `1.5-2.0`, чтобы лучше решать проблемы региональных блокировок. +* **Откат при проблемах:** если после обновления появились ошибки, которых раньше точно не было, можно открыть `issue` и временно откатиться на версию **1.0.6**. + +--- + +## Как это работает + +```text +Android-приложение → VpnService / WireGuard GoBackend → локальный UDP 127.0.0.1:9000 + → Go-клиент WDTT → VK TURN / DTLS → wdtt-server на VPS → интернет +``` + +1. Приложение запускает нативный Go-клиент `libclient.so` и передаёт ему адрес VPS, VK-хеши звонка, пароль туннеля, протокол TURN и количество потоков. +2. Go-клиент получает TURN-учётные данные через VK-звонок, при необходимости решает VK Smart Captcha и устанавливает DTLS-соединения через TURN relay. +3. Первый рабочий канал запрашивает у VPS WireGuard-конфигурацию через `GETCONF`, передавая локальный порт, `device-id` и пароль подключения. +4. Сервер проверяет пароль: главный пароль работает как владелец, сгенерированные пароли могут иметь срок действия и привязываются к первому устройству. +5. Android-часть парсит полученный WireGuard-конфиг, поднимает системный VPN-туннель и применяет исключения приложений. +6. Watchdog следит за Go-процессом, активными воркерами и сетевыми изменениями, перезапуская транспорт при сбоях. + +## Быстрый старт + +1. Скачайте актуальный `APK` со **[страницы релизов](https://github.com/amurcanov/proxy-turn-vk-android/releases)**. +2. Установите приложение на Android-смартфон. +3. Подготовьте VPS с root-доступом или пользователем с `sudo`. +4. В VK создайте или откройте групповой звонок и скопируйте ссылку вида `vk.com/call/join/xxxxxxxxxxx`. +5. Откройте **WDTT** и перейдите во вкладку **«Деплой»**. +6. Введите IP/домен VPS, SSH-логин, пароль и SSH-порт. +7. В **«Секретах»** задайте пароль туннеля. При необходимости добавьте Telegram `admin_id` и `bot_token` для управления паролями. +8. Нажмите **«Установить»** и дождитесь завершения деплоя. +9. Во вкладке **«Туннель»** укажите IP/домен сервера, VK-хеши, пароль туннеля и количество потоков. +10. Нажмите **«Подключить»** и выдайте Android-разрешение на VPN. + +--- + +## Получение VK-хеша + +```text +VK → группа → звонок → ссылка приглашения → код после /join/ +``` + +1. Откройте VK и создайте пустую группу или используйте существующую. +2. Начните групповой звонок. +3. Скопируйте ссылку приглашения. +4. Вставьте в WDTT всю ссылку или только хеш после последнего слэша. +5. Можно использовать до **3 хешей** одновременно для распределения нагрузки и увеличения доступного числа потоков. + +> [!IMPORTANT] +> При выходе из звонка нажимайте **«Просто завершить»**, а не **«Завершить для всех»**. Если закрыть комнату для всех участников, хеш перестанет работать. + +## Деплой VPS + +Серверная часть ставится автоматически из приложения: + +```text +Android → SSH → /tmp/deploy.sh + /tmp/wdtt-server → /usr/local/bin/wdtt-server + → systemd wdtt.service → wdtt0 + NAT + firewall +``` + +По умолчанию используются: + +- `56000/udp` — DTLS-сервер WDTT. +- `56001/udp` — внутренний WireGuard-порт сервера. +- `9000/udp` — локальный порт Android-клиента. +- `10.66.66.0/24` — подсеть WireGuard-устройств. + +Если включить ручное управление портами, эти значения можно изменить в **«Секретах»**. + +## Управление доступом + +WDTT-сервер поддерживает две модели подключения: + +- **Главный пароль:** задаётся при деплое и используется владельцем сервера. +- **Сгенерированные пароли:** создаются через Telegram-бота командой `/new`, имеют срок действия и привязываются к первому устройству. + +Команда `/list` показывает активные пароли и устройства. Через inline-кнопки можно отвязать устройство или удалить пароль. + +--- + +## Дополнительные возможности + +#### Исключения приложений + +Вкладка **«Исключ.»** показывает установленные приложения с поиском. В режиме ЧС выбранные приложения исключаются из VPN, а в режиме БС логика инвертируется: неотмеченные приложения добавляются в туннель. Само приложение WDTT и VK-клиенты исключаются автоматически, чтобы не ломать TURN-соединение. + +#### Логирование + +Вкладка **«Логи»** показывает статус получения VK-учётных данных, решение капчи, DTLS-handshake, готовность WireGuard, статистику активных воркеров и ошибки. Повторяющиеся строки схлопываются в одну запись со счётчиком. + +#### Обновления + +Приложение проверяет **GitHub releases** репозитория [amurcanov/proxy-turn-vk-android](https://github.com/amurcanov/proxy-turn-vk-android), умеет показывать диалог новой версии и открывать страницу релиза в браузере. + +#### Отчёт для issue + +В разделе **«Информация»** есть кнопка **«Собрать отчёт»**. Она копирует версию приложения, Android SDK, ABI, модель устройства, SoC, ROM и fingerprint — эти данные полезны при разборе крашей и проблем с запуском. + +--- + +> [!NOTE] +> ### Отчёты об ошибках +> WDTT зависит от мобильной сети, Android-ограничений фоновой работы, состояния VK-звонка, TURN-квот и настроек VPS. +> +> Если возникла проблема, приложите к `issue` отчёт из раздела **«Информация»**, скриншот вкладки **«Логи»**, версию APK, ABI сборки и описание сети. Мелкие повторяющиеся ошибки в логах не всегда означают поломку, если туннель остаётся активным. + +> [!IMPORTANT] +> ### Назначение проекта +> Приложение является техническим инструментом для защищённого туннелирования собственного трафика через ваш сервер. Автор не призывает использовать WDTT для противоправных целей или нарушения правил сторонних сервисов. + +--- + +## Лицензия + +Этот проект распространяется под лицензией **GNU General Public License v3.0**. diff --git a/app/build.gradle.kts b/app/build.gradle.kts new file mode 100644 index 0000000..4684a50 --- /dev/null +++ b/app/build.gradle.kts @@ -0,0 +1,143 @@ +import java.util.Properties + +plugins { + id("com.android.application") + id("org.jetbrains.kotlin.plugin.compose") +} + +android { + namespace = "com.wdtt.client" + compileSdk = 35 + + defaultConfig { + applicationId = "com.wdtt.client" + minSdk = 29 + targetSdk = 35 + versionCode = 118 + versionName = "1.1.8" + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + vectorDrawables { + useSupportLibrary = true + } + + ndk { + abiFilters.addAll(listOf("arm64-v8a", "armeabi-v7a", "x86_64")) + } + } + + splits { + abi { + isEnable = true + reset() + include("arm64-v8a", "armeabi-v7a", "x86_64") + isUniversalApk = true + } + } + + val localProperties = Properties() + val localPropertiesFile = rootProject.file("local.properties") + if (localPropertiesFile.exists()) { + localProperties.load(localPropertiesFile.inputStream()) + } + + signingConfigs { + create("release") { + val keyFile = localProperties.getProperty("KEYSTORE_FILE") + if (keyFile != null) { + // Резолвим путь: если начинается с "..", берём от корня проекта + val resolvedFile = if (keyFile.startsWith("..")) { + // ../release.keystore -> корень проекта / release.keystore + file(rootDir.resolve(keyFile.substring(3))) + } else { + file(keyFile) + } + if (resolvedFile.exists()) { + storeFile = resolvedFile + storePassword = localProperties.getProperty("KEYSTORE_PASSWORD") + keyAlias = localProperties.getProperty("KEY_ALIAS") + keyPassword = localProperties.getProperty("KEY_PASSWORD") + } else { + println("WARNING: Keystore file not found: $keyFile (resolved: ${resolvedFile.absolutePath})") + } + } + enableV1Signing = true + enableV2Signing = true + enableV3Signing = true + } + } + + buildTypes { + getByName("release") { + isMinifyEnabled = true + isShrinkResources = true + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + val keyFile = localProperties.getProperty("KEYSTORE_FILE") + val resolvedFile = if (keyFile != null && keyFile.startsWith("..")) { + file(rootDir.resolve(keyFile.substring(3))) + } else if (keyFile != null) { + file(keyFile) + } else null + + if (resolvedFile != null && resolvedFile.exists()) { + signingConfig = signingConfigs.getByName("release") + println("✅ Signing config applied: ${resolvedFile.absolutePath}") + } else { + println("⚠️ WARNING: Keystore not found, using debug signing") + println(" Looked for: ${resolvedFile?.absolutePath ?: keyFile}") + } + } + } + + packaging { + jniLibs { + useLegacyPackaging = true + } + resources { + excludes += "/META-INF/{AL2.0,LGPL2.1}" + excludes += "/META-INF/INDEX.LIST" + excludes += "/META-INF/DEPENDENCIES" + } + } + + buildFeatures { + compose = true + buildConfig = true + } + + lint { + checkReleaseBuilds = false + abortOnError = false + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + + sourceSets { + getByName("main") { + jniLibs.setSrcDirs(listOf("src/main/jniLibs")) + } + } +} + +dependencies { + implementation("androidx.core:core-ktx:1.15.0") + implementation(platform("androidx.compose:compose-bom:2024.12.01")) + implementation("androidx.compose.ui:ui") + implementation("androidx.compose.ui:ui-graphics") + implementation("androidx.compose.ui:ui-tooling-preview") + implementation("androidx.compose.foundation:foundation") + implementation("androidx.compose.material3:material3") + implementation("androidx.compose.material:material-icons-extended") + implementation("androidx.activity:activity-compose:1.9.3") + implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.8.7") + implementation("androidx.lifecycle:lifecycle-runtime-compose:2.8.7") + implementation("androidx.datastore:datastore-preferences:1.1.1") + implementation("com.wireguard.android:tunnel:1.0.20230706") + implementation("com.github.mwiede:jsch:0.2.16") +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..b24c6a2 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,4 @@ +-keep class com.jcraft.jsch.** { *; } +-keep class com.mwiede.jsch.** { *; } +-dontwarn com.jcraft.jsch.** +-dontwarn com.mwiede.jsch.** diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..2952449 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/assets/deploy.sh b/app/src/main/assets/deploy.sh new file mode 100644 index 0000000..ecf78a5 --- /dev/null +++ b/app/src/main/assets/deploy.sh @@ -0,0 +1,585 @@ +#!/bin/bash +# ============================================================================== +# WDTT VPN Server — Универсальный установщик для VPS +# Поддержка: Debian 11+, Ubuntu 20.04+, CentOS/RHEL/Fedora/AlmaLinux/Rocky +# Версия: 3.2 | Дата: 2026-05-13 +# NAT: MASQUERADE через iptables +# WG: порт 56001 (не конфликтует с существующим WG на 51820) +# DTLS: порт 56000 +# ============================================================================== +set -uo pipefail + +readonly SCRIPT_VERSION="3.2" +readonly LOG_FILE="/var/log/wdtt-install.log" +readonly WG_PORT="${WDTT_WG_PORT:-56001}" +readonly DTLS_PORT="${WDTT_DTLS_PORT:-56000}" +readonly SSH_PORT="${WDTT_SSH_PORT:-22}" +readonly WDTT_ARGS="${WDTT_ARGS:-}" +readonly WDTT_IFACE="wdtt0" +readonly WDTT_CONFIG_DIR="/etc/wdtt" +readonly WDTT_ACCESS_DB="passwords.json" +readonly IPT_COMMENT="WDTT_MANAGED" +readonly IPT_MIRROR_COMMENT="WDTT_MIRRORED" + +validate_port() { + local name="$1" value="$2" + case "$value" in + ''|*[!0-9]*) die "$name должен быть числом от 1 до 65535, получено: $value" ;; + esac + if [ "$value" -lt 1 ] || [ "$value" -gt 65535 ]; then + die "$name должен быть в диапазоне 1..65535, получено: $value" + fi +} + +# ─── Цвета ─────────────────────────────────────────────────────────────────── +C_GREEN=''; C_YELLOW=''; C_RED='' +C_CYAN=''; C_BOLD=''; C_NC='' + +log_info() { echo -e "${C_GREEN}[✓]${C_NC} $*" | tee -a "$LOG_FILE"; } +log_warn() { echo -e "${C_YELLOW}[!]${C_NC} $*" | tee -a "$LOG_FILE"; } +log_error() { echo -e "${C_RED}[✗]${C_NC} $*" | tee -a "$LOG_FILE"; } +log_step() { echo -e "${C_CYAN}[►]${C_NC} ${C_BOLD}$*${C_NC}" | tee -a "$LOG_FILE"; } + +die() { log_error "$*"; exit 1; } + +prog() { echo "WDTT_PROGRESS|$1|$2"; } + +# ─── Проверка root ──────────────────────────────────────────────────────────── +check_root() { + if [ "$(id -u)" -ne 0 ]; then + die "Скрипт должен быть запущен от root. Если sudo отсутствует, зайдите под root и запустите: bash $0 $*" + fi +} + +# ─── Определение ОС ────────────────────────────────────────────────────────── +OS_ID="" ; PKG_MGR="" + +detect_os() { + log_step "Определение операционной системы..." + if [ ! -f /etc/os-release ]; then + die "Файл /etc/os-release не найден." + fi + . /etc/os-release + OS_ID="${ID:-unknown}" + case "$OS_ID" in + ubuntu|debian|linuxmint|pop) PKG_MGR="apt" ;; + centos|rhel|rocky|almalinux|oracle) PKG_MGR="yum" + command -v dnf &>/dev/null && PKG_MGR="dnf" ;; + fedora) PKG_MGR="dnf" ;; + arch|manjaro|endeavouros) PKG_MGR="pacman" ;; + *) die "Неподдерживаемый дистрибутив: $OS_ID" ;; + esac + log_info "ОС: ${PRETTY_NAME:-$OS_ID} | PM: $PKG_MGR" +} + +# ─── Пакеты ────────────────────────────────────────────────────────────────── +pkg_update_done=0 + +pkg_update() { + [ "$pkg_update_done" = "1" ] && return 0 + log_step "Обновление индексов пакетов..." + case "$PKG_MGR" in + apt) + export DEBIAN_FRONTEND=noninteractive + apt-get update -y >>"$LOG_FILE" 2>&1 || log_warn "apt update завершился с ошибкой, пробую продолжить" + ;; + dnf) dnf makecache -y >>"$LOG_FILE" 2>&1 || true ;; + yum) yum makecache -y >>"$LOG_FILE" 2>&1 || true ;; + pacman) pacman -Sy --noconfirm >>"$LOG_FILE" 2>&1 || true ;; + esac + pkg_update_done=1 +} + +pkg_install() { + [ "$#" -eq 0 ] && return 0 + case "$PKG_MGR" in + apt) + export DEBIAN_FRONTEND=noninteractive + apt-get install -y -qq "$@" >>"$LOG_FILE" 2>&1 + ;; + dnf) dnf install -y "$@" >>"$LOG_FILE" 2>&1 ;; + yum) yum install -y "$@" >>"$LOG_FILE" 2>&1 ;; + pacman) pacman -S --noconfirm --needed "$@" >>"$LOG_FILE" 2>&1 ;; + esac +} + +install_prerequisites() { + prog 0.08 "Пакеты..." + pkg_update + log_step "Установка базовых зависимостей..." + + case "$PKG_MGR" in + apt) + pkg_install ca-certificates iproute2 iptables nftables procps psmisc || \ + log_warn "Часть apt-пакетов не установилась, продолжаю с доступными утилитами" + ;; + dnf|yum) + pkg_install ca-certificates iproute iptables nftables procps-ng psmisc || \ + log_warn "Часть rpm-пакетов не установилась, продолжаю с доступными утилитами" + ;; + pacman) + pkg_install ca-certificates iproute2 iptables nftables procps-ng psmisc || \ + log_warn "Часть pacman-пакетов не установилась, продолжаю с доступными утилитами" + ;; + esac +} + +require_runtime_tools() { + command -v ip >/dev/null 2>&1 || die "Команда ip не найдена. Установите iproute2/iproute." + command -v systemctl >/dev/null 2>&1 || die "systemctl не найден. Нужен VPS с systemd." +} + +# ─── Автоопределение WAN-интерфейса ────────────────────────────────────────── +detect_wan_interface() { + local iface="" + iface=$(ip route show default 2>/dev/null | head -1 | awk '{for(i=1;i<=NF;i++) if($i=="dev") print $(i+1)}') + [ -z "$iface" ] && iface=$(ip -4 addr show scope global 2>/dev/null | grep -oP '(?<=dev )\S+' | head -1) + [ -z "$iface" ] && iface=$(ls /sys/class/net/ | grep -v lo | head -1) + echo "$iface" +} + +# ─── Firewall helpers ──────────────────────────────────────────────────────── +FW_BACKEND="" + +iptables_add_input() { + local proto="$1" port="$2" comment="$3" + [ "$FW_BACKEND" = "iptables" ] || return 0 + case "$proto:$port" in + tcp:[0-9]*|udp:[0-9]*) ;; + *) return 0 ;; + esac + [ "$port" -ge 1 ] 2>/dev/null && [ "$port" -le 65535 ] 2>/dev/null || return 0 + iptables -C INPUT -p "$proto" --dport "$port" -m comment --comment "$comment" -j ACCEPT 2>/dev/null || \ + iptables -I INPUT -p "$proto" --dport "$port" -m comment --comment "$comment" -j ACCEPT 2>/dev/null || true +} + +mirror_port_to_iptables() { + local proto="$1" port="$2" source="$3" + iptables_add_input "$proto" "$port" "$IPT_MIRROR_COMMENT" + log_info "iptables: сохранён доступ $port/$proto из $source" +} + +mirror_existing_firewall_ports_to_iptables() { + [ "$FW_BACKEND" = "iptables" ] || return 0 + local tmp + tmp="$(mktemp)" + + if command -v ufw >/dev/null 2>&1 && ufw status 2>/dev/null | grep -qi "Status: active"; then + log_info "UFW активен: переношу разрешённые tcp/udp порты в iptables" + ufw status 2>/dev/null | sed -nE 's#^([0-9]{1,5})/(tcp|udp)[[:space:]].*ALLOW IN.*#\2 \1 ufw#p' >> "$tmp" || true + fi + + if command -v nft >/dev/null 2>&1; then + local nft_ports + nft_ports="$(nft -a list ruleset 2>/dev/null | sed -nE 's/.*(tcp|udp) dport ([0-9]{1,5}).*accept.*/\1 \2 nft/p' | sort -u || true)" + if [ -n "$nft_ports" ]; then + log_info "nftables найден: переношу простые accept dport правила в iptables" + printf '%s\n' "$nft_ports" >> "$tmp" + fi + fi + + if [ -s "$tmp" ]; then + sort -u "$tmp" | while read -r proto port source; do + mirror_port_to_iptables "$proto" "$port" "$source" + done + else + log_info "UFW/nftables разрешённых tcp/udp портов для переноса не найдено" + fi + rm -f "$tmp" +} + +detect_firewall() { + if ! command -v iptables &>/dev/null; then + log_warn "iptables не найден. Пытаюсь установить firewall-пакеты..." + pkg_update + pkg_install iptables nftables || true + fi + if command -v iptables &>/dev/null; then + FW_BACKEND="iptables" + log_info "Firewall backend: iptables (принудительно)" + mirror_existing_firewall_ports_to_iptables + else + FW_BACKEND="none" + log_warn "iptables не найден. Установка продолжится, но NAT/firewall нужно настроить вручную." + fi +} + +# ─── Firewall-абстракция ───────────────────────────────────────────────────── +fw_add_input_udp() { + local port="$1" + case "$FW_BACKEND" in + iptables) + iptables -C INPUT -p udp --dport "$port" -m comment --comment "$IPT_COMMENT" -j ACCEPT 2>/dev/null || \ + iptables -I INPUT -p udp --dport "$port" -m comment --comment "$IPT_COMMENT" -j ACCEPT 2>/dev/null || true + ;; + nft) + ensure_nft_wdtt + nft add rule inet wdtt input udp dport "$port" accept 2>/dev/null || true + ;; + none) ;; + esac +} + +fw_add_input_tcp() { + local port="$1" + case "$FW_BACKEND" in + iptables) + iptables -C INPUT -p tcp --dport "$port" -m comment --comment "$IPT_COMMENT" -j ACCEPT 2>/dev/null || \ + iptables -I INPUT -p tcp --dport "$port" -m comment --comment "$IPT_COMMENT" -j ACCEPT 2>/dev/null || true + ;; + nft) + ensure_nft_wdtt + nft add rule inet wdtt input tcp dport "$port" accept 2>/dev/null || true + ;; + none) ;; + esac +} + +fw_add_input_udp_range() { + local from="$1" to="$2" + case "$FW_BACKEND" in + iptables|nft) log_warn "Пропускаю широкий UDP range $from-$to: это не изолировано и может влиять на чужие сервисы." ;; + none) ;; + esac +} + +fw_add_forward() { + case "$FW_BACKEND" in + iptables) + iptables -C FORWARD -i "$WDTT_IFACE" -m comment --comment "$IPT_COMMENT" -j ACCEPT 2>/dev/null || \ + iptables -I FORWARD -i "$WDTT_IFACE" -m comment --comment "$IPT_COMMENT" -j ACCEPT 2>/dev/null || true + iptables -C FORWARD -o "$WDTT_IFACE" -m comment --comment "$IPT_COMMENT" -j ACCEPT 2>/dev/null || \ + iptables -I FORWARD -o "$WDTT_IFACE" -m comment --comment "$IPT_COMMENT" -j ACCEPT 2>/dev/null || true + ;; + nft) + ensure_nft_wdtt + nft add rule inet wdtt forward iifname "$WDTT_IFACE" accept 2>/dev/null || true + nft add rule inet wdtt forward oifname "$WDTT_IFACE" accept 2>/dev/null || true + ;; + none) ;; + esac +} + +fw_add_masquerade() { + local iface="$1" subnet="$2" + case "$FW_BACKEND" in + iptables) + iptables -t nat -C POSTROUTING -s "$subnet" -o "$iface" -m comment --comment "$IPT_COMMENT" -j MASQUERADE 2>/dev/null || \ + iptables -t nat -A POSTROUTING -s "$subnet" -o "$iface" -m comment --comment "$IPT_COMMENT" -j MASQUERADE 2>/dev/null || true + ;; + nft) + nft add table ip wdtt 2>/dev/null || true + nft add chain ip wdtt postrouting '{ type nat hook postrouting priority 100; }' 2>/dev/null || true + nft add rule ip wdtt postrouting ip saddr "$subnet" oifname "$iface" masquerade 2>/dev/null || true + ;; + none) ;; + esac +} + +fw_add_mss_clamping() { + local subnet="$1" + case "$FW_BACKEND" in + iptables) + # Применяем правило ТОЛЬКО к нашей подсети WDTT + iptables -t mangle -C FORWARD -s "$subnet" -p tcp -m tcp --tcp-flags SYN,RST SYN -m comment --comment "$IPT_COMMENT" -j TCPMSS --clamp-mss-to-pmtu 2>/dev/null || \ + iptables -t mangle -I FORWARD -s "$subnet" -p tcp -m tcp --tcp-flags SYN,RST SYN -m comment --comment "$IPT_COMMENT" -j TCPMSS --clamp-mss-to-pmtu 2>/dev/null || true + iptables -t mangle -C FORWARD -d "$subnet" -p tcp -m tcp --tcp-flags SYN,RST SYN -m comment --comment "$IPT_COMMENT" -j TCPMSS --clamp-mss-to-pmtu 2>/dev/null || \ + iptables -t mangle -I FORWARD -d "$subnet" -p tcp -m tcp --tcp-flags SYN,RST SYN -m comment --comment "$IPT_COMMENT" -j TCPMSS --clamp-mss-to-pmtu 2>/dev/null || true + ;; + nft) + nft add table inet wdtt_mangle 2>/dev/null || true + nft add chain inet wdtt_mangle forward '{ type filter hook forward priority -150; policy accept; }' 2>/dev/null || true + nft add rule inet wdtt_mangle forward ip saddr "$subnet" tcp flags syn tcp option maxseg size set rt mtu 2>/dev/null || true + nft add rule inet wdtt_mangle forward ip daddr "$subnet" tcp flags syn tcp option maxseg size set rt mtu 2>/dev/null || true + ;; + none) ;; + esac +} + +fw_add_established() { + return 0 +} + +fw_cleanup_wdtt_rules() { + local iface="$1" + if command -v iptables >/dev/null 2>&1; then + for i in {1..5}; do + local nat_iface + for nat_iface in "$iface" $(ls /sys/class/net 2>/dev/null || true); do + [ -n "$nat_iface" ] && iptables -t nat -D POSTROUTING -s 10.66.66.0/24 -o "$nat_iface" -m comment --comment "$IPT_COMMENT" -j MASQUERADE 2>/dev/null || true + done + iptables -t mangle -D FORWARD -s 10.66.66.0/24 -p tcp -m tcp --tcp-flags SYN,RST SYN -m comment --comment "$IPT_COMMENT" -j TCPMSS --clamp-mss-to-pmtu 2>/dev/null || true + iptables -t mangle -D FORWARD -d 10.66.66.0/24 -p tcp -m tcp --tcp-flags SYN,RST SYN -m comment --comment "$IPT_COMMENT" -j TCPMSS --clamp-mss-to-pmtu 2>/dev/null || true + iptables -D INPUT -p udp --dport ${DTLS_PORT} -m comment --comment "$IPT_COMMENT" -j ACCEPT 2>/dev/null || true + iptables -D INPUT -p udp --dport ${WG_PORT} -m comment --comment "$IPT_COMMENT" -j ACCEPT 2>/dev/null || true + iptables -D INPUT -p tcp --dport ${SSH_PORT} -m comment --comment "$IPT_COMMENT" -j ACCEPT 2>/dev/null || true + iptables -D INPUT -p tcp --dport 22 -m comment --comment "$IPT_COMMENT" -j ACCEPT 2>/dev/null || true + iptables -D FORWARD -i "$WDTT_IFACE" -m comment --comment "$IPT_COMMENT" -j ACCEPT 2>/dev/null || true + iptables -D FORWARD -o "$WDTT_IFACE" -m comment --comment "$IPT_COMMENT" -j ACCEPT 2>/dev/null || true + done + fi + if command -v nft >/dev/null 2>&1; then + nft delete table ip wdtt 2>/dev/null || true + nft delete table inet wdtt 2>/dev/null || true + nft delete table inet wdtt_mangle 2>/dev/null || true + fi +} + +cleanup_config_dir_keep_access_db() { + [ -d "$WDTT_CONFIG_DIR" ] || return 0 + find "$WDTT_CONFIG_DIR" -mindepth 1 -maxdepth 1 ! -name "$WDTT_ACCESS_DB" -exec rm -rf {} + 2>/dev/null || true + [ -f "$WDTT_CONFIG_DIR/$WDTT_ACCESS_DB" ] && chmod 600 "$WDTT_CONFIG_DIR/$WDTT_ACCESS_DB" 2>/dev/null || true +} + +# ══════════════════════════════════════════════════════════════════════════════ +# WDTT VPN SERVER DEPLOYMENT +# ══════════════════════════════════════════════════════════════════════════════ + +# ─── Очистка старого WDTT ───────────────────────────────────────────────────── +wdtt_cleanup() { + prog 0.05 "Очистка..." + echo "🧹 Очистка старой установки WDTT..." + + systemctl unmask wdtt 2>/dev/null || true + systemctl stop wdtt 2>/dev/null || true + systemctl disable wdtt 2>/dev/null || true + rm -f /etc/systemd/system/wdtt.service 2>/dev/null || true + systemctl daemon-reload 2>/dev/null || true + pkill -x wdtt-server 2>/dev/null || killall wdtt-server 2>/dev/null || true + + # Удаляем только собственный интерфейс WDTT. + ip link show "$WDTT_IFACE" >/dev/null 2>&1 && ip link del "$WDTT_IFACE" 2>/dev/null || true + + # Удаляем старые правила NAT для WDTT подсети + fw_cleanup_wdtt_rules "$(detect_wan_interface)" + + rm -f /usr/local/bin/wdtt-server 2>/dev/null || true + cleanup_config_dir_keep_access_db + + echo "✓ Очистка завершена (база доступа сохранена)" +} + +# ─── Sysctl тюнинг ─────────────────────────────────────────────────────────── +setup_sysctl() { + prog 0.20 "Sysctl..." + echo "⚙️ Настройка сетевых параметров..." + + echo 1 > /proc/sys/net/ipv4/ip_forward 2>/dev/null || true + mkdir -p /etc/sysctl.d + cat > /etc/sysctl.d/99-wdtt.conf << 'SYSEOF' +net.ipv4.ip_forward = 1 +SYSEOF + + sysctl -p /etc/sysctl.d/99-wdtt.conf >/dev/null 2>&1 || true + + echo "✓ Sysctl настроен" +} + +# ─── Настройка NAT + Firewall ───────────────────────────────────────────────── +setup_nat_and_firewall() { + prog 0.40 "NAT + Firewall..." + echo "🛡 Настройка NAT и фаервола..." + + local iface + iface=$(detect_wan_interface) + + if [ -z "$iface" ]; then + log_warn "Не удалось определить WAN-интерфейс!" + log_warn "Настройте NAT вручную для подсети 10.66.66.0/24." + return 0 + fi + + log_info "WAN-интерфейс: $iface" + + # === WDTT порты === + fw_add_input_udp "$DTLS_PORT" # 56000 — DTLS сервер + fw_add_input_udp "$WG_PORT" # 56001 — WireGuard + fw_add_input_tcp "$SSH_PORT" # SSH порт, указанный пользователем в приложении + + # === Forward === + fw_add_forward + + # === NAT: MASQUERADE для подсети WireGuard === + fw_add_masquerade "$iface" "10.66.66.0/24" + + # === MSS Clamping для исправления MTU (DonationAlerts / Cloudflare) === + fw_add_mss_clamping "10.66.66.0/24" + + if [ "$FW_BACKEND" = "none" ]; then + echo "⚠ NAT не настроен автоматически: firewall-бэкенд отсутствует" + else + echo "✓ NAT: MASQUERADE на $iface для 10.66.66.0/24" + fi + echo "✓ Порты: ${DTLS_PORT}/udp(DTLS), ${WG_PORT}/udp(WG), ${SSH_PORT}/tcp(SSH)" + echo "✓ TCP MSS Clamping включен" +} + +# ─── Установка бинарника wdtt-server ────────────────────────────────────────── +setup_wdtt_binary() { + prog 0.60 "Бинарник..." + echo "📦 Установка wdtt-server..." + + if [ -f /tmp/wdtt-server ]; then + chmod +x /tmp/wdtt-server + install -m 0755 /tmp/wdtt-server /usr/local/bin/wdtt-server 2>/dev/null || mv /tmp/wdtt-server /usr/local/bin/wdtt-server + echo "✓ wdtt-server установлен" + elif [ -f /usr/local/bin/wdtt-server ]; then + echo "✓ wdtt-server уже установлен" + else + echo "⚠ wdtt-server не найден в /tmp/ — пропускаем" + echo " Загрузите бинарник вручную в /usr/local/bin/wdtt-server" + fi + + mkdir -p "$WDTT_CONFIG_DIR" +} + +# ─── Systemd-сервис WDTT ───────────────────────────────────────────────────── +setup_wdtt_service() { + prog 0.75 "Сервис..." + echo "🔧 Создание systemd-сервиса WDTT..." + + cat > /etc/systemd/system/wdtt.service << WDTTSVC +[Unit] +Description=WDTT VPN Server +After=network.target network-online.target +Wants=network-online.target + +[Service] +Type=simple +ExecStartPre=-/usr/bin/env bash -c "ip link show ${WDTT_IFACE} >/dev/null 2>&1 && ip link del ${WDTT_IFACE} 2>/dev/null || true" +ExecStartPre=-/usr/bin/env bash -c "if command -v iptables >/dev/null 2>&1; then iptables -C INPUT -p udp --dport ${DTLS_PORT} -m comment --comment ${IPT_COMMENT} -j ACCEPT 2>/dev/null || iptables -I INPUT -p udp --dport ${DTLS_PORT} -m comment --comment ${IPT_COMMENT} -j ACCEPT; iptables -C INPUT -p udp --dport ${WG_PORT} -m comment --comment ${IPT_COMMENT} -j ACCEPT 2>/dev/null || iptables -I INPUT -p udp --dport ${WG_PORT} -m comment --comment ${IPT_COMMENT} -j ACCEPT; iptables -C INPUT -p tcp --dport ${SSH_PORT} -m comment --comment ${IPT_COMMENT} -j ACCEPT 2>/dev/null || iptables -I INPUT -p tcp --dport ${SSH_PORT} -m comment --comment ${IPT_COMMENT} -j ACCEPT; fi" +ExecStart=/usr/local/bin/wdtt-server -listen 0.0.0.0:${DTLS_PORT} -wg-port ${WG_PORT} -config-dir ${WDTT_CONFIG_DIR} ${WDTT_ARGS} +Restart=always +RestartSec=5 +LimitNOFILE=65535 + +[Install] +WantedBy=multi-user.target +WDTTSVC + + systemctl daemon-reload + systemctl unmask wdtt >/dev/null 2>&1 || true + systemctl enable wdtt >/dev/null 2>&1 || true + echo "✓ Сервис wdtt.service создан и включён" +} + +# ─── Запуск WDTT ───────────────────────────────────────────────────────────── +start_wdtt() { + prog 0.90 "Запуск..." + echo "🚀 Запуск WDTT VPN Server..." + + if [ ! -f /usr/local/bin/wdtt-server ]; then + echo "⚠ wdtt-server не установлен — запуск пропущен" + return 0 + fi + + systemctl restart wdtt + + sleep 2 + local status + status=$(systemctl is-active wdtt 2>/dev/null || echo "unknown") + + prog 1.0 "Готово!" + + echo "" + echo "══════════════════════════════════════════════════════════════" + + if [ "$status" = "active" ]; then + echo "✅ Деплой успешно завершён!" + echo " NAT: MASQUERADE (стандартный)" + echo " DTLS: порт ${DTLS_PORT}" + echo " WG: порт ${WG_PORT}" + echo " SSH: порт ${SSH_PORT}" + else + echo "⚠️ Сервис wdtt не запустился. Статус: $status" + echo " Последние логи:" + journalctl -u wdtt -n 7 --no-pager 2>/dev/null | sed 's/^/ >> /' + fi + + echo " Логи: journalctl -u wdtt -f" + echo " Статус: systemctl status wdtt" + echo "══════════════════════════════════════════════════════════════" + echo "" +} + +# ─── Команда: uninstall ────────────────────────────────────────────────────── +do_uninstall() { + log_step "Удаление WDTT..." + + systemctl stop wdtt 2>/dev/null || true + systemctl disable wdtt 2>/dev/null || true + rm -f /etc/systemd/system/wdtt.service + systemctl daemon-reload + + ip link show "$WDTT_IFACE" >/dev/null 2>&1 && ip link del "$WDTT_IFACE" 2>/dev/null || true + pkill -x wdtt-server 2>/dev/null || true + + fw_cleanup_wdtt_rules "$(detect_wan_interface)" + + rm -f /usr/local/bin/wdtt-server + cleanup_config_dir_keep_access_db + rm -f /etc/sysctl.d/99-wdtt.conf + sysctl --system >/dev/null 2>&1 || true + + log_info "WDTT удалён. База доступа сохранена: ${WDTT_CONFIG_DIR}/${WDTT_ACCESS_DB}" +} + +# ─── Команда: status ───────────────────────────────────────────────────────── +do_status() { + echo "Статус WDTT:" + echo "" + if systemctl is-active wdtt &>/dev/null; then + log_info "Сервис: АКТИВЕН" + else + log_warn "Сервис: НЕ АКТИВЕН" + fi + if [ -f /usr/local/bin/wdtt-server ]; then + log_info "Бинарник: установлен" + else + log_warn "Бинарник: НЕ найден" + fi + if ip link show "$WDTT_IFACE" &>/dev/null; then + log_info "WDTT интерфейс ($WDTT_IFACE): активен" + else + log_warn "WDTT интерфейс ($WDTT_IFACE): не активен" + fi +} + +# ══════════════════════════════════════════════════════════════════════════════ +# MAIN +# ══════════════════════════════════════════════════════════════════════════════ +main() { + echo "╔══════════════════════════════════════════════════════════════╗" + echo "║ WDTT VPN Server — Installer v${SCRIPT_VERSION} ║" + echo "║ DTLS: ${DTLS_PORT} | WG: ${WG_PORT} | SSH: ${SSH_PORT} ║" + echo "╚══════════════════════════════════════════════════════════════╝" + + local action="${1:-install}" + check_root + validate_port "WDTT_DTLS_PORT" "$DTLS_PORT" + validate_port "WDTT_WG_PORT" "$WG_PORT" + validate_port "WDTT_SSH_PORT" "$SSH_PORT" + + mkdir -p "$(dirname "$LOG_FILE")" + echo "=== WDTT Installer v${SCRIPT_VERSION} — $(date) ===" >> "$LOG_FILE" + + detect_os + install_prerequisites + require_runtime_tools + detect_firewall + + case "$action" in + status|--status|-s) do_status ;; + uninstall|--uninstall|-u) do_uninstall ;; + install|--install|-i|*) + wdtt_cleanup + setup_sysctl + setup_nat_and_firewall + setup_wdtt_binary + setup_wdtt_service + start_wdtt + ;; + esac +} + +main "$@" diff --git a/app/src/main/ic_launcher-playstore.png b/app/src/main/ic_launcher-playstore.png new file mode 100644 index 0000000000000000000000000000000000000000..17fc07a3e23425c001e10c0ee88fc23220a7545b GIT binary patch literal 334012 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