├── .github └── workflows │ └── pypi-publish.yml ├── .gitignore ├── .images ├── Termux-SSH 1280x640 px.png └── Termux-SSH-v1.1.0.png ├── LICENSE ├── README.md ├── install.sh ├── poetry.lock ├── pyproject.toml └── termux_ssh ├── __init__.py ├── __main__.py └── termux.py /.github/workflows/pypi-publish.yml: -------------------------------------------------------------------------------- 1 | # This workflow will upload a Python Package using Twine when a release is created 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries 3 | 4 | # This workflow uses actions that are not certified by GitHub. 5 | # They are provided by a third-party and are governed by 6 | # separate terms of service, privacy policy, and support 7 | # documentation. 8 | 9 | name: Upload Python Package to PyPi 10 | 11 | on: 12 | release: 13 | types: [published] 14 | 15 | permissions: 16 | contents: read 17 | 18 | jobs: 19 | deploy: 20 | runs-on: ubuntu-latest 21 | environment: release 22 | permissions: 23 | # IMPORTANT: this permission is mandatory for trusted publishing 24 | id-token: write 25 | 26 | steps: 27 | - uses: actions/checkout@v3 28 | - name: Set up Python 29 | uses: actions/setup-python@v3 30 | with: 31 | python-version: "3.11" 32 | - name: Install dependencies 33 | run: | 34 | python -m pip install --upgrade pip 35 | pip install build 36 | - name: Build package 37 | run: | 38 | python -m build 39 | - name: Publish package 40 | uses: pypa/gh-action-pypi-publish@v1.8.10 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.toptal.com/developers/gitignore/api/python 3 | # Edit at https://www.toptal.com/developers/gitignore?templates=python 4 | 5 | ### Python ### 6 | # Byte-compiled / optimized / DLL files 7 | __pycache__/ 8 | *.py[cod] 9 | *$py.class 10 | 11 | # C extensions 12 | *.so 13 | 14 | # Distribution / packaging 15 | .Python 16 | build/ 17 | develop-eggs/ 18 | dist/ 19 | downloads/ 20 | eggs/ 21 | .eggs/ 22 | lib/ 23 | lib64/ 24 | parts/ 25 | sdist/ 26 | var/ 27 | wheels/ 28 | share/python-wheels/ 29 | *.egg-info/ 30 | .installed.cfg 31 | *.egg 32 | MANIFEST 33 | 34 | # PyInstaller 35 | # Usually these files are written by a python script from a template 36 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 37 | *.manifest 38 | *.spec 39 | 40 | # Installer logs 41 | pip-log.txt 42 | pip-delete-this-directory.txt 43 | 44 | # Unit test / coverage reports 45 | htmlcov/ 46 | .tox/ 47 | .nox/ 48 | .coverage 49 | .coverage.* 50 | .cache 51 | nosetests.xml 52 | coverage.xml 53 | *.cover 54 | *.py,cover 55 | .hypothesis/ 56 | .pytest_cache/ 57 | cover/ 58 | 59 | # Translations 60 | *.mo 61 | *.pot 62 | 63 | # Django stuff: 64 | *.log 65 | local_settings.py 66 | db.sqlite3 67 | db.sqlite3-journal 68 | 69 | # Flask stuff: 70 | instance/ 71 | .webassets-cache 72 | 73 | # Scrapy stuff: 74 | .scrapy 75 | 76 | # Sphinx documentation 77 | docs/_build/ 78 | 79 | # PyBuilder 80 | .pybuilder/ 81 | target/ 82 | 83 | # Jupyter Notebook 84 | .ipynb_checkpoints 85 | 86 | # IPython 87 | profile_default/ 88 | ipython_config.py 89 | 90 | # pyenv 91 | # For a library or package, you might want to ignore these files since the code is 92 | # intended to run in multiple environments; otherwise, check them in: 93 | # .python-version 94 | 95 | # pipenv 96 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 97 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 98 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 99 | # install all needed dependencies. 100 | #Pipfile.lock 101 | 102 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 103 | __pypackages__/ 104 | 105 | # Celery stuff 106 | celerybeat-schedule 107 | celerybeat.pid 108 | 109 | # SageMath parsed files 110 | *.sage.py 111 | 112 | # Environments 113 | .env 114 | .venv 115 | env/ 116 | venv/ 117 | ENV/ 118 | env.bak/ 119 | venv.bak/ 120 | termuxenv 121 | 122 | # Spyder project settings 123 | .spyderproject 124 | .spyproject 125 | 126 | # Rope project settings 127 | .ropeproject 128 | 129 | # mkdocs documentation 130 | /site 131 | 132 | # mypy 133 | .mypy_cache/ 134 | .dmypy.json 135 | dmypy.json 136 | 137 | # Pyre type checker 138 | .pyre/ 139 | 140 | # pytype static type analyzer 141 | .pytype/ 142 | 143 | # Cython debug symbols 144 | cython_debug/ 145 | 146 | # End of https://www.toptal.com/developers/gitignore/api/python 147 | -------------------------------------------------------------------------------- /.images/Termux-SSH 1280x640 px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmdhrumilmistry/Termux-SSH/0ec5488e2756dc84ae7c60f730c57d5161c8f8eb/.images/Termux-SSH 1280x640 px.png -------------------------------------------------------------------------------- /.images/Termux-SSH-v1.1.0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmdhrumilmistry/Termux-SSH/0ec5488e2756dc84ae7c60f730c57d5161c8f8eb/.images/Termux-SSH-v1.1.0.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 dmdhrumilmistry 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Termux-SSH 4 | 5 | ``` 6 | +-----------------------------------------------------------+ 7 | | _____ _____ _____ _ _ | 8 | ||_ _| / ___/ ___| | | | | 9 | | | | ___ _ __ _ __ ___ _ ___ __ \ `--.\ `--.| |_| | | 10 | | | |/ _ \ '__| '_ ` _ \| | | \ \/ / `--. \`--. \ _ | | 11 | | | | __/ | | | | | | | |_| |> < /\__/ /\__/ / | | | | 12 | | \_/\___|_| |_| |_| |_|\__,_/_/\_\ \____/\____/\_| |_/ | 13 | | A tool by Dhrumil Mistry | 14 | +-----------------------------------------------------------+ 15 | | ~ ~ ~ ~ ~ A tool Specially Designed for Termux ~ ~ ~ ~ ~ | 16 | +-----------------------------------------------------------+ 17 | ``` 18 | 19 | Termux SSH helps user to setup SSH server on termux android application, which will help them to execute commands remotely using a command line. 20 | If your device is rooted then you can have full control over the android smartphone. You can take screenshots, record and capture audio, video, images remotely using termux apis. 21 | 22 | > This feature might not work on few devices. Refer [Termux-API documentation](https://wiki.termux.com/wiki/Termux:API) for more information. 23 | 24 | ## Screenshot 25 | 26 | ![Termux-SSH](https://github.com/dmdhrumilmistry/Termux-SSH/blob/main/.images/Termux-SSH-v1.1.0.png?raw=true) 27 | 28 | ## Installation 29 | 30 | ### Using bash script 31 | 32 | - Execute command in Termux App 33 | 34 | ```bash 35 | cd $HOME && mkdir tmp && cd tmp && curl -O https://raw.githubusercontent.com/dmdhrumilmistry/Termux-SSH/main/install.sh && chmod +x $HOME/tmp/install.sh && ./install.sh; cd $HOME ;rm -rf $HOME/tmp 36 | ``` 37 | 38 | ### Maually 39 | 40 | - Open Termux terminal 41 | 42 | - Install Python and git packages 43 | 44 | ```bash 45 | pkg install python git -y 46 | ``` 47 | 48 | - Install required packages 49 | 50 | ```bash 51 | pip install git+https://github.com/dmdhrumilmistry/Termux-SSH.git 52 | ``` 53 | 54 | - Start Termux-SSH and Install required tools 55 | 56 | ```bash 57 | python -m termux_ssh 58 | ``` 59 | 60 | ```bash 61 | install 62 | ``` 63 | 64 | ## Commands List 65 | 66 | | command | description | 67 | | :-----: | :------------------------------------------- | 68 | | install | installs required tools | 69 | | start | starts SSH server | 70 | | clear | clears console screen | 71 | | port | checks on which port server is running | 72 | | user | get username | 73 | | genpass | generates new password for user | 74 | | wlanip | get wlan ip of the device | 75 | | conncmd | connect to this using using command printed | 76 | | torssh | start ssh service on tor network | 77 | | torhost | get TOR network hostname | 78 | | torstop | exit tor network | 79 | | restart | restarts ssh server | 80 | | close | exits Termux-SSH without stopping SSH server | 81 | | exit | stops ssh server and exit | 82 | 83 | ### Features 84 | 85 | - Helps user to setup basic SSH server 86 | - Automated Setup 87 | - Instructed Steps 88 | - Secure script 89 | 90 | ### Dependencies 91 | 92 | **`Termux-SSH`** requires following programs to run properly - 93 | 94 | - `Python` 95 | - `subprocess module` 96 | - `colorama` 97 | - `prettytable` 98 | - `netifaces` 99 | - `OpenSSH` 100 | - `Nmap` 101 | - `termux-api` 102 | - `termux-auth` 103 | 104 | > All the dependencies will be installed automatically when you run install.py script 105 | 106 | ## [License](https://github.com/dmdhrumilmistry/Termux-SSH/blob/main/LICENSE) 107 | 108 | MIT License 109 | 110 | ### Have any Issues? 111 | 112 | Create an issue from **_[Issues Tab](https://github.com/dmdhrumilmistry/Termux-SSH/issues)_** 113 | 114 | ## Leave A Star⭐ 115 | 116 | ## Video Tutorial 117 | 118 | - For Previous Version 119 |
120 | 121 | ### Support Me on 122 | 123 | | Platforms | | 124 | | :------------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------: | 125 | | [![GithubBadge](https://img.shields.io/badge/Github-dmdhrumilmistry-333)](https://github.com/dmdhrumilmistry) | [![LinkedIn](https://img.shields.io/badge/LinkedIn-Dhrumil%20Mistry-4078c0)](https://linkedin.com/in/dmdhrumilmistry) | 126 | | [![Instagram](https://img.shields.io/badge/Instagram-dmdhrumilmistry-833ab4)](https://www.instagram.com/dmdhrumilmistry/) | [![Twitter](https://img.shields.io/badge/Twitter-dmdhrumilmistry-4078c0)](https://twitter.com/dmdhrumilmistry) | 127 | | [![YouTube](https://img.shields.io/badge/YouTube-Dhrumil%20Mistry-critical)](https://www.youtube.com/channel/UChbjrRvbzgY3BIomUI55XDQ) | [![BlogSpot](https://img.shields.io/badge/Blog-Dhrumil%20Mistry-bd2c00)](https://dmdhrumilmistry.github.io/blog) | 128 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo -e "\033[33m[*] Starting installation...\033[0m" 4 | apt update -y 5 | apt install python git openssh termux-auth termux-api tor proxychains-ng -y 6 | pip install git+https://github.com/dmdhrumilmistry/Termux-SSH.git 7 | echo -e "\033[33m[*] Completed... Start Termux-SSH using python -m termux_ssh and use install command to complete setup.\033[0m"; 8 | -------------------------------------------------------------------------------- /poetry.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. 2 | 3 | [[package]] 4 | name = "colorama" 5 | version = "0.4.6" 6 | description = "Cross-platform colored terminal text." 7 | optional = false 8 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" 9 | files = [ 10 | {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, 11 | {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, 12 | ] 13 | 14 | [[package]] 15 | name = "netifaces" 16 | version = "0.11.0" 17 | description = "Portable network interface information." 18 | optional = false 19 | python-versions = "*" 20 | files = [ 21 | {file = "netifaces-0.11.0-cp27-cp27m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:eb4813b77d5df99903af4757ce980a98c4d702bbcb81f32a0b305a1537bdf0b1"}, 22 | {file = "netifaces-0.11.0-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:5f9ca13babe4d845e400921973f6165a4c2f9f3379c7abfc7478160e25d196a4"}, 23 | {file = "netifaces-0.11.0-cp27-cp27m-win32.whl", hash = "sha256:7dbb71ea26d304e78ccccf6faccef71bb27ea35e259fb883cfd7fd7b4f17ecb1"}, 24 | {file = "netifaces-0.11.0-cp27-cp27m-win_amd64.whl", hash = "sha256:0f6133ac02521270d9f7c490f0c8c60638ff4aec8338efeff10a1b51506abe85"}, 25 | {file = "netifaces-0.11.0-cp27-cp27mu-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:08e3f102a59f9eaef70948340aeb6c89bd09734e0dca0f3b82720305729f63ea"}, 26 | {file = "netifaces-0.11.0-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:c03fb2d4ef4e393f2e6ffc6376410a22a3544f164b336b3a355226653e5efd89"}, 27 | {file = "netifaces-0.11.0-cp34-cp34m-win32.whl", hash = "sha256:73ff21559675150d31deea8f1f8d7e9a9a7e4688732a94d71327082f517fc6b4"}, 28 | {file = "netifaces-0.11.0-cp35-cp35m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:815eafdf8b8f2e61370afc6add6194bd5a7252ae44c667e96c4c1ecf418811e4"}, 29 | {file = "netifaces-0.11.0-cp35-cp35m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:50721858c935a76b83dd0dd1ab472cad0a3ef540a1408057624604002fcfb45b"}, 30 | {file = "netifaces-0.11.0-cp35-cp35m-win32.whl", hash = "sha256:c9a3a47cd3aaeb71e93e681d9816c56406ed755b9442e981b07e3618fb71d2ac"}, 31 | {file = "netifaces-0.11.0-cp36-cp36m-macosx_10_15_x86_64.whl", hash = "sha256:aab1dbfdc55086c789f0eb37affccf47b895b98d490738b81f3b2360100426be"}, 32 | {file = "netifaces-0.11.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c37a1ca83825bc6f54dddf5277e9c65dec2f1b4d0ba44b8fd42bc30c91aa6ea1"}, 33 | {file = "netifaces-0.11.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:28f4bf3a1361ab3ed93c5ef360c8b7d4a4ae060176a3529e72e5e4ffc4afd8b0"}, 34 | {file = "netifaces-0.11.0-cp36-cp36m-win32.whl", hash = "sha256:2650beee182fed66617e18474b943e72e52f10a24dc8cac1db36c41ee9c041b7"}, 35 | {file = "netifaces-0.11.0-cp36-cp36m-win_amd64.whl", hash = "sha256:cb925e1ca024d6f9b4f9b01d83215fd00fe69d095d0255ff3f64bffda74025c8"}, 36 | {file = "netifaces-0.11.0-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:84e4d2e6973eccc52778735befc01638498781ce0e39aa2044ccfd2385c03246"}, 37 | {file = "netifaces-0.11.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:18917fbbdcb2d4f897153c5ddbb56b31fa6dd7c3fa9608b7e3c3a663df8206b5"}, 38 | {file = "netifaces-0.11.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:48324183af7f1bc44f5f197f3dad54a809ad1ef0c78baee2c88f16a5de02c4c9"}, 39 | {file = "netifaces-0.11.0-cp37-cp37m-win32.whl", hash = "sha256:8f7da24eab0d4184715d96208b38d373fd15c37b0dafb74756c638bd619ba150"}, 40 | {file = "netifaces-0.11.0-cp37-cp37m-win_amd64.whl", hash = "sha256:2479bb4bb50968089a7c045f24d120f37026d7e802ec134c4490eae994c729b5"}, 41 | {file = "netifaces-0.11.0-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:3ecb3f37c31d5d51d2a4d935cfa81c9bc956687c6f5237021b36d6fdc2815b2c"}, 42 | {file = "netifaces-0.11.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:96c0fe9696398253f93482c84814f0e7290eee0bfec11563bd07d80d701280c3"}, 43 | {file = "netifaces-0.11.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:c92ff9ac7c2282009fe0dcb67ee3cd17978cffbe0c8f4b471c00fe4325c9b4d4"}, 44 | {file = "netifaces-0.11.0-cp38-cp38-win32.whl", hash = "sha256:d07b01c51b0b6ceb0f09fc48ec58debd99d2c8430b09e56651addeaf5de48048"}, 45 | {file = "netifaces-0.11.0-cp38-cp38-win_amd64.whl", hash = "sha256:469fc61034f3daf095e02f9f1bbac07927b826c76b745207287bc594884cfd05"}, 46 | {file = "netifaces-0.11.0-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:5be83986100ed1fdfa78f11ccff9e4757297735ac17391b95e17e74335c2047d"}, 47 | {file = "netifaces-0.11.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:54ff6624eb95b8a07e79aa8817288659af174e954cca24cdb0daeeddfc03c4ff"}, 48 | {file = "netifaces-0.11.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:841aa21110a20dc1621e3dd9f922c64ca64dd1eb213c47267a2c324d823f6c8f"}, 49 | {file = "netifaces-0.11.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:e76c7f351e0444721e85f975ae92718e21c1f361bda946d60a214061de1f00a1"}, 50 | {file = "netifaces-0.11.0.tar.gz", hash = "sha256:043a79146eb2907edf439899f262b3dfe41717d34124298ed281139a8b93ca32"}, 51 | ] 52 | 53 | [[package]] 54 | name = "prettytable" 55 | version = "3.10.0" 56 | description = "A simple Python library for easily displaying tabular data in a visually appealing ASCII table format" 57 | optional = false 58 | python-versions = ">=3.8" 59 | files = [ 60 | {file = "prettytable-3.10.0-py3-none-any.whl", hash = "sha256:6536efaf0757fdaa7d22e78b3aac3b69ea1b7200538c2c6995d649365bddab92"}, 61 | {file = "prettytable-3.10.0.tar.gz", hash = "sha256:9665594d137fb08a1117518c25551e0ede1687197cf353a4fdc78d27e1073568"}, 62 | ] 63 | 64 | [package.dependencies] 65 | wcwidth = "*" 66 | 67 | [package.extras] 68 | tests = ["pytest", "pytest-cov", "pytest-lazy-fixtures"] 69 | 70 | [[package]] 71 | name = "wcwidth" 72 | version = "0.2.13" 73 | description = "Measures the displayed width of unicode strings in a terminal" 74 | optional = false 75 | python-versions = "*" 76 | files = [ 77 | {file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"}, 78 | {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"}, 79 | ] 80 | 81 | [metadata] 82 | lock-version = "2.0" 83 | python-versions = "^3.9" 84 | content-hash = "c8a68dca2f45b78735b22b4573766c1bc9b0b1ea9457e6ec33c47756ac85d1b9" 85 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "termux-ssh" 3 | version = "1.2.0" 4 | description = "Termux SSH helps you to setup SSH server on termux application on android, which helps you to execute tasks remotely through terminal/cmd/powershell/termux" 5 | authors = ["Dhrumil Mistry <56185972+dmdhrumilmistry@users.noreply.github.com>"] 6 | license = "MIT" 7 | readme = "README.md" 8 | 9 | [tool.poetry.dependencies] 10 | python = "^3.11" 11 | colorama = "^0.4.6" 12 | prettytable = "^3.10.0" 13 | netifaces = "^0.11.0" 14 | 15 | 16 | [build-system] 17 | requires = ["poetry-core"] 18 | build-backend = "poetry.core.masonry.api" 19 | -------------------------------------------------------------------------------- /termux_ssh/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmdhrumilmistry/Termux-SSH/0ec5488e2756dc84ae7c60f730c57d5161c8f8eb/termux_ssh/__init__.py -------------------------------------------------------------------------------- /termux_ssh/__main__.py: -------------------------------------------------------------------------------- 1 | from os import name 2 | from sys import exit 3 | 4 | from .termux import ( 5 | BRIGHT_RED, 6 | BRIGHT_YELLOW, 7 | RESET_COLORS, 8 | BRIGHT_WHITE, 9 | BRIGHT_GREEN, 10 | clear_console, 11 | cowsay_banner, 12 | exception_message, 13 | exit_program, 14 | get_ssh_port, 15 | get_user, 16 | generate_passwd, 17 | get_tor_hostname, 18 | get_wlan_ip, 19 | restart_ssh, 20 | show_connect_command, 21 | start_ssh, 22 | start_tor_ssh, 23 | stop_tor, 24 | help, 25 | install_cmd, 26 | ) 27 | 28 | 29 | if name == 'nt': 30 | print(BRIGHT_RED + '[-] Termux-SSH is created for Termux Application on Android.') 31 | print(BRIGHT_YELLOW + '[!] Exiting Termux-SSH') 32 | exit() 33 | 34 | 35 | clear_console() 36 | cowsay_banner() 37 | print(BRIGHT_YELLOW + "[Note] Termux-SSH only works in Termux Android Application.") 38 | 39 | 40 | while True: 41 | try: 42 | 43 | cmd = input(BRIGHT_YELLOW + "Termux-SSH >> " + RESET_COLORS).lower().strip() 44 | 45 | match cmd: 46 | case 'exit': 47 | exit_program(kill_ssh_server=True, kill_tor_server=True) 48 | 49 | case 'close': 50 | exit_program() 51 | 52 | case 'help': 53 | help() 54 | 55 | case 'clear': 56 | clear_console() 57 | 58 | case 'install': 59 | install_cmd() 60 | 61 | case 'start': 62 | if start_ssh(): 63 | print(BRIGHT_WHITE + '[*] SSH started successfully') 64 | else: 65 | print(BRIGHT_RED + '[-] Cannot Start SSH Server') 66 | 67 | case 'port': 68 | ssh_port = get_ssh_port() 69 | if ssh_port: 70 | print(BRIGHT_WHITE + f'[*] PORT : {ssh_port}') 71 | else: 72 | print(BRIGHT_YELLOW + '[!] Start SSH server before finding the port') 73 | 74 | case 'user': 75 | username = get_user() 76 | print(BRIGHT_WHITE + f'[*] USER : {username}') 77 | 78 | case 'genpass': 79 | generate_passwd() 80 | 81 | case 'wlanip': 82 | wlan_ip = get_wlan_ip() 83 | print(BRIGHT_WHITE + f'[*] WLAN IP : {wlan_ip}') 84 | 85 | case 'conncmd': 86 | show_connect_command() 87 | 88 | case 'torssh': 89 | start_tor_ssh() 90 | print(BRIGHT_GREEN + "[*] SSH can be connected over TOR.") 91 | 92 | case 'torhost': 93 | hostname = get_tor_hostname() 94 | if hostname != "": 95 | print(BRIGHT_GREEN + f"[*] Hostname : {hostname}") 96 | else: 97 | print(BRIGHT_RED + "[X] Cannot find hostname, try using install command.") 98 | 99 | case 'torstop': 100 | stop_tor() 101 | print(BRIGHT_GREEN + "[*] SSH over TOR stopped successfully.") 102 | 103 | case 'restart': 104 | restart_ssh() 105 | 106 | case _: 107 | print(BRIGHT_RED + '[!] INVALID COMMAND') 108 | 109 | except (EOFError, KeyboardInterrupt): 110 | print(BRIGHT_RED + "\n[-] User interruption detected! Services will be running in background") 111 | exit_program() 112 | 113 | except Exception as e: 114 | exception_message(e) 115 | -------------------------------------------------------------------------------- /termux_ssh/termux.py: -------------------------------------------------------------------------------- 1 | from sys import exit 2 | from time import sleep 3 | 4 | from colorama import Style, Fore 5 | from prettytable import PrettyTable 6 | 7 | 8 | import colorama 9 | import textwrap 10 | import os 11 | import re 12 | import subprocess 13 | import netifaces as nic 14 | 15 | 16 | # for terminal colors 17 | colorama.init(autoreset=True) 18 | BRIGHT_WHITE = Style.BRIGHT + Fore.WHITE 19 | BRIGHT_YELLOW = Style.BRIGHT + Fore.YELLOW 20 | BRIGHT_RED = Style.BRIGHT + Fore.RED 21 | BRIGHT_GREEN = Style.BRIGHT + Fore.GREEN 22 | BRIGHT_LYELLOW = Style.BRIGHT + Fore.LIGHTYELLOW_EX 23 | RESET_COLORS = Style.RESET_ALL 24 | 25 | 26 | # commands menu table 27 | menu = PrettyTable(['command', 'description']) 28 | menu.add_row(['install', 'installs required tools']) 29 | menu.add_row(['start', 'starts SSH server']) 30 | menu.add_row(['clear', 'clears console screen']) 31 | menu.add_row(['port', 'checks on which port server is running']) 32 | menu.add_row(['user', 'get username']) 33 | menu.add_row(['genpass', 'generates new password for user']) 34 | menu.add_row(['wlanip', 'get wlan ip of the device']) 35 | menu.add_row(['conncmd', 'connect to this using using command printed']) 36 | menu.add_row(['torssh', 'start ssh service on tor network']) 37 | menu.add_row(['torhost', 'get TOR network hostname']) 38 | menu.add_row(['torstop', 'exit tor network']) 39 | menu.add_row(['restart', 'restarts ssh server']) 40 | menu.add_row(['close', 'exits Termux-SSH without stopping SSH server']) 41 | menu.add_row(['exit', 'stops ssh server and exit']) 42 | 43 | 44 | # tor commands and confs 45 | HOME = os.environ["HOME"] 46 | PREFIX = os.environ.get("PREFIX", "/data/data/com.termux/files/usr/") 47 | ALIAS_FILE = os.path.join(HOME, ".tor_ssh_aliases") 48 | SHELL = os.environ['SHELL'].split('/')[-1] 49 | 50 | SSH_CONFIG_FILE = os.path.join(PREFIX, 'etc', 'ssh', 'sshd_config') 51 | 52 | TOR_SSH_DIR = os.path.join(PREFIX, 'var', 'lib', 'tor', 'hidden_ssh') 53 | HOSTNAME_FILE = os.path.join(TOR_SSH_DIR, "hostname") 54 | TORRC_FILE = os.path.join(TOR_SSH_DIR, 'torrc') 55 | tor_start = f'tor -f {TORRC_FILE} &' 56 | tor_stop = 'pkill -9 tor' 57 | 58 | 59 | # functions 60 | def cowsay_banner(): 61 | ''' 62 | description: prints cowsay banner 63 | ''' 64 | print(BRIGHT_GREEN + r""" 65 | +-----------------------------+ 66 | | ____________ | 67 | |< Termux-SSH > | 68 | | ------------ | 69 | | \ ^__^ | 70 | | \ (oo)\_______ | 71 | | (__)\ )\/\ | 72 | | ||----w | | 73 | | || || | 74 | +-----------------------------+ 75 | |Author: dmdhrumilmistry | 76 | +-----------------------------+ 77 | """) 78 | 79 | 80 | def help(): 81 | ''' 82 | description: prints help menu commands 83 | ''' 84 | print(menu) 85 | 86 | 87 | def clear_console(): 88 | ''' 89 | description: clears console 90 | ''' 91 | subprocess.call('clear', shell=True) 92 | 93 | 94 | def get_user(): 95 | ''' 96 | description: get username of the termux user 97 | returns: username(str) 98 | ''' 99 | return subprocess.check_output("whoami", shell=True).decode('utf-8').strip() 100 | 101 | 102 | def generate_passwd(): 103 | ''' 104 | description: create new password for the termux user 105 | ''' 106 | user = get_user() 107 | print(BRIGHT_WHITE + f"\n[!] Creating new password for user {user} ") 108 | print(BRIGHT_YELLOW + "Note: You will be asked to enter password, You must enter the same password while connecting.") 109 | subprocess.call('passwd', shell=True) 110 | 111 | 112 | def install_cmd(): 113 | ''' 114 | description: handles install command 115 | ''' 116 | clear_console() 117 | install_termux_req() 118 | conf_tor() 119 | generate_passwd() 120 | 121 | 122 | def install_termux_req(): 123 | ''' 124 | description: installs requirements 125 | ''' 126 | cowsay_banner() 127 | print(BRIGHT_YELLOW + '\n[*] Installing required packages') 128 | 129 | print(BRIGHT_YELLOW + '\n[*] Updating...') 130 | subprocess.call("pkg update -y", shell=True) 131 | 132 | print(BRIGHT_YELLOW + '\n[*] Upgrading...') 133 | subprocess.call("pkg upgrade -y", shell=True) 134 | 135 | print(BRIGHT_YELLOW + '\n[*] Installing requirements ...') 136 | subprocess.call( 137 | "pkg install nmap openssh termux-auth termux-api tor proxychains-ng -y", shell=True) 138 | 139 | print(BRIGHT_YELLOW + '\n[*] Installation completed!!\n') 140 | 141 | print(BRIGHT_YELLOW + "[*] Clearing Screen in...", end="") 142 | for _ in range(5, 0, -1): 143 | print(_, end="...") 144 | sleep(0.35) 145 | print() 146 | clear_console() 147 | cowsay_banner() 148 | 149 | 150 | def conf_tor(): 151 | ''' 152 | description: configure termux-ssh for tor network 153 | returns: bool 154 | ''' 155 | # delete and create new directory 156 | os.system(f"rm -rf {TOR_SSH_DIR}") 157 | os.system(f"mkdir -p {TOR_SSH_DIR}") 158 | 159 | # configure shell 160 | shell_conf = {'bash': '.bashrc', 'zsh': '.zshrc'} 161 | SHELL_RC_FILE = os.path.join(HOME, shell_conf.get(SHELL, '')) 162 | 163 | # create aliases 164 | print(BRIGHT_YELLOW + "[*] Generating aliases...") 165 | aliases = textwrap.dedent(f''' 166 | ################### 167 | # TOR SSH aliases 168 | 169 | alias tor-ssh-start="{tor_start}" 170 | alias tor-ssh-stop="{tor_stop}"''') 171 | with open(ALIAS_FILE, 'w') as f: 172 | f.write(aliases) 173 | 174 | if SHELL_RC_FILE != "": 175 | with open(SHELL_RC_FILE, 'a+') as f: 176 | f.write(f'\nsource {ALIAS_FILE}\n') 177 | print(BRIGHT_YELLOW + "[*] Restart Termux before using SSH over TOR.") 178 | else: 179 | print( 180 | BRIGHT_RED + f"[X] add alias file {ALIAS_FILE} to .bashrc/.zshrc file manually.") 181 | 182 | # TORRC CONF 183 | print(BRIGHT_YELLOW + '\n[*] Generating torrc file ...') 184 | 185 | torrc = textwrap.dedent(f''' 186 | ## Enable TOR SOCKS proxy 187 | SOCKSPort 127.0.0.1:9050 188 | 189 | ## Hidden Service: SSH 190 | HiddenServiceDir {TOR_SSH_DIR} 191 | HiddenServicePort 22 127.0.0.1:8022\n\n''') 192 | 193 | # write conf file to torrc 194 | with open(TORRC_FILE, 'w+') as conf_file: 195 | conf_file.write(torrc) 196 | 197 | print(BRIGHT_YELLOW + '\n[*] Generating hostname for TOR Network ...') 198 | os.system(f'tor -f {TORRC_FILE} &') 199 | 200 | print(BRIGHT_YELLOW + 201 | '\n[*] Waiting for 30s for hostname to be generated ...') 202 | sleep(30) 203 | 204 | print(BRIGHT_YELLOW + '\n[*] Killing TOR service ...') 205 | os.system("pkill -9 tor") 206 | 207 | print(BRIGHT_YELLOW + '\n[*] Extracting hostname ...') 208 | if os.path.isfile(HOSTNAME_FILE): 209 | with open(HOSTNAME_FILE, 'r') as f: 210 | hostname = f.read() 211 | if hostname != "": 212 | print(BRIGHT_GREEN + f"HOSTNAME : {hostname}") 213 | return True 214 | print(BRIGHT_RED + "Hostname has not been generated. run tor manually to generate hostname") 215 | return False 216 | 217 | 218 | def get_tor_hostname(): 219 | ''' 220 | description: gets tor hostname which will be used to connect 221 | ''' 222 | return subprocess.check_output(f"cat {HOSTNAME_FILE}", shell=True, executable=os.environ["SHELL"]).decode('utf-8') 223 | 224 | 225 | def start_ssh(): 226 | ''' 227 | description: starts ssh server 228 | returns: bool 229 | ''' 230 | try: 231 | subprocess.call("sshd &", shell=True) 232 | return True 233 | except Exception as e: 234 | exception_message(e) 235 | return False 236 | 237 | 238 | def get_ssh_port(): 239 | ''' 240 | description: get ssh server port 241 | returns: str or None 242 | ''' 243 | if start_ssh(): 244 | # get port from config file: $PREFIX/etc/ssh/sshd_config 245 | ssh_config = '' 246 | with open(SSH_CONFIG_FILE, 'r') as f: 247 | ssh_config = f.read() 248 | 249 | matches = re.search(r'Port\s+(\d+)', ssh_config) 250 | port = matches.group(1) if matches else '8022' 251 | 252 | return port 253 | 254 | 255 | def get_wlan_ip(): 256 | ''' 257 | description: get wlan0 device ip assigned by router/DHCP 258 | returns: str or None 259 | ''' 260 | return nic.ifaddresses('wlan0')[nic.AF_INET][0]['addr'] 261 | 262 | 263 | def kill_ssh(): 264 | ''' 265 | description: kills ssh server 266 | returns: bool 267 | ''' 268 | try: 269 | subprocess.call("pkill sshd", shell=True) 270 | return True 271 | except Exception as e: 272 | exception_message(e) 273 | return False 274 | 275 | 276 | def restart_ssh(): 277 | ''' 278 | description: restarts ssh server 279 | ''' 280 | if kill_ssh(): 281 | print(Style.BRIGHT + '[*] SSH Server Successfully Killed.') 282 | if start_ssh(): 283 | print(Style.BRIGHT + '[*] SSH Server Successfully Started.') 284 | 285 | 286 | def exception_message(exception: Exception): 287 | ''' 288 | description: handles exception by printing message and exception 289 | ''' 290 | print(BRIGHT_RED + 291 | '[-] An Error occured while running the script, please create an issue on github to resolve issue and make script better.') 292 | print(BRIGHT_YELLOW + 293 | '[*] Github URL: https://github.com/dmrdhrumilmistry/Termux-SSH ') 294 | print(f'{BRIGHT_RED}{Exception}') 295 | 296 | 297 | def exit_program(kill_ssh_server: bool = False, kill_tor_server: bool = False): 298 | ''' 299 | description: closes ssh server and exits the program 300 | ''' 301 | print(BRIGHT_RED + '[*] Exiting Program... Please be patient...') 302 | if kill_ssh_server: 303 | kill_ssh() 304 | if kill_tor_server: 305 | stop_tor() 306 | 307 | exit() 308 | 309 | 310 | def show_connect_command(): 311 | ''' 312 | description: prints ssh command to help user to connect to the Termux terminal 313 | ''' 314 | user = get_user() 315 | wlan_ip = get_wlan_ip() 316 | ssh_port = get_ssh_port() 317 | 318 | print(BRIGHT_WHITE + f'[+] USER : {user}') 319 | print(BRIGHT_WHITE + f'[+] IP : {wlan_ip}') 320 | print(BRIGHT_WHITE + f'[+] PORT : {ssh_port}') 321 | 322 | print(BRIGHT_WHITE + 'Use below command to connect:') 323 | print(BRIGHT_LYELLOW + f'ssh {user}@{wlan_ip} -p {ssh_port}\n') 324 | 325 | 326 | def start_tor_ssh(): 327 | ''' 328 | description: starts ssh over 329 | ''' 330 | start_ssh() 331 | subprocess.call(tor_start, shell=True, executable=os.environ["SHELL"], stdout=subprocess.PIPE) 332 | 333 | 334 | def stop_tor(): 335 | ''' 336 | description: stops tor network 337 | ''' 338 | subprocess.call(tor_stop, shell=True, executable=os.environ["SHELL"]) 339 | --------------------------------------------------------------------------------