├── .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 | 
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 | | [](https://github.com/dmdhrumilmistry) | [](https://linkedin.com/in/dmdhrumilmistry) |
126 | | [](https://www.instagram.com/dmdhrumilmistry/) | [](https://twitter.com/dmdhrumilmistry) |
127 | | [](https://www.youtube.com/channel/UChbjrRvbzgY3BIomUI55XDQ) | [](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 |
--------------------------------------------------------------------------------