3.1 Crypted and key
The proposed dyDNS is similar to the ssh public key protocol. In the ssh protocol, the public key is an encrypted file, id_rsa.pub stored in .ssh directory of the user home directory. In dyDNS, encrypted information is stored in .freedns directory. When dyDNS is called, encrypted file, crypted will be decrypted within Python script without exposing plain text information. Decryption needs a key which is stored in .freedns directory where the key file should be readable only to the account owner.
The following is the procedure for creating two files, crypted and key, in the .freedns directory:
1.You must create .freedns directory in your home directory.
$ cd
$ mkdir .freedns
$ cd .freedns
2.In .freedns directory, you should create a plain authentication file in plain text: freedns.info.
freedns.info file has three lines (username, password, dynamic domain name).
$ cat freedns.info
USERNAME = "username_freedns.afraid.org"
PASSWORD = "password_freedns.afraid.org"
UPDATE_DOMAINS = ["your_domain_name", ]
3. Create a plain file of encryption/decryption key for OpenSSL.
key file must contain a string or strings with any characters.
$ cat key
your_key
4. Change to the key file permission that only you can read.
$ chmod 700 key
5. Encrypt freedns.info to crypted file.
$ openssl enc -e -aes256 -pbkdf2 -in freedns.info -out crypted -k `cat key`
6. Delete freedns.info file for security.
$ rm freedns.info
7. ".freedns" directory has two files: crypted and key
$ ls
crypted key
3.2 How to install and run dyDNS
PyPI packaging allows dyDNS to run on Windows, MacOS, and Linux OSs without being aware of operating systems. You must install Python3.8 in your environment. Select the right file from the following site:
https://docs.conda.io/en/latest/miniconda.html
To install dyDNS, run the following pip command in the terminal:
$ pip install dyDNS
To run dyDNS,
$ dydns
There are two types of messages from freedns.afraid.org: no-update message and updated message.
No update includes “Errors:” which is not an error, but no-update message.
3.3 Encryption/Decryption in dydns.py
The following program can read the crypted information and decrypt it to the plain text. When Python is installed, OpenSSL will be automatically installed. OpenSSL can encrypt and decrypt any information. This example shows aes256 decryption. The 256-bit AES cipher is a technique that uses a key length of 256 bits for this process. Since the number of key combinations increases exponentially with key size, an AES-256 key is mathematically equivalent to having 2256 possible combinations:
openssl enc -d -aes256 -pbkdf2 -in '+home+'/.freedns/crypted -out result -k '+ str(key)
import subprocess as sp
from os.path import expanduser
home = expanduser("~")
k=open(home+'/.freedns/key','r')
key=k.read()
sp.call('openssl enc -d -aes256 -pbkdf2 -in '+home+'/.freedns/crypted -out result -k '+ str(key),shell=True)
f=open('result','r')
lines=f.read()
print(lines)
sp.call('rm result',shell=True)
USERNAME = str(lines.split('\n',1)[0].split('"')[1])
PASSWORD = str(lines.split('\n',2)[1].split('"')[1])
DOMAIN = str(lines.split('\n',3)[2].split('"')[1])
UPDATE_DOMAINS = [DOMAIN, ]
The source code of dydns.py is included in APPENDIX. read_url plays a key role in activating dynamic DNS update. Accessing the designated URL can activate updating a new IP for dynamic DNS.
def read_url(url):
try:
return str(urlopen(url).read())
except (URLError,HTTPError,ContentTooShortError) as inst:
return "ERROR: {0}".format(inst).encode('utf-8')
The other dynamic DNS providers use the similar protocol with URL, for example, in dynv6:
http://dynv6.com/api/update?hostname=<domain>\&token=<password>\&ipv4=<IP>
Remember that such protocols use unsecured plain text.
3.4 PyPI packaging
PyPI packaging needs three files such as README.md, setup.py and dydns.py. README.md can be created with github using REAME file option. setup.py can be downloaded from the pypi site. Run the following command to download the source files from the following site:
https://files.pythonhosted.org/packages/03/d2/b83426ddcca2568a4acd6da8df3fa85c3862a823927911b8078522fb1118/dyDNS-0.0.2.tar.gz
And expand it by the following command.
$ tar xvf dyDNS-0.0.2.tar.gz
$ cd dyDNS-0.0.2/
tree command shows the structure of directory and files.
$ tree .
.
├── PKG-INFO
├── README.md
├── setup.cfg
├── setup.py
└── src
├── dyDNS.egg-info
│ ├── PKG-INFO
│ ├── SOURCES.txt
│ ├── dependency_links.txt
│ ├── entry_points.txt
│ └── top_level.txt
└── dydns.py
Then, take a look at the content of setup.py file by the following command:
$ cat setup.py
import setuptools
with open("README.md", "r", encoding="utf-8") as fh:
long_description = fh.read()
setuptools.setup(
name="dyDNS",
version="0.0.2",
author="yoshiyasu takefuji",
author_email="[email protected]",
description="activating dynamicDNS for freedns.afraid.org",
long_description=long_description,
long_description_content_type="text/markdown",
url="https://github.com/ytakefuji/dyDNS",
project_urls={
"Bug Tracker": "https://github.com/ytakefuji/dyDNS",
},
classifiers=[
"Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
],
package_dir={"": "src"},
py_modules=['dydns'],
packages=setuptools.find_packages(where="src"),
python_requires=">=3.7",
entry_points = {
'console_scripts': [
'dydns = dydns:main'
]
},
)
Shaded lines indicate that ten modifications are needed for your application.
In order to debut a new PyPI package, you need to create a new account on pypi site: Go to https://pypi.org/account/register/
Make sure that you should have username, password and Two factor authentication (2FA) for generating API token.
You must create a .pypirc file with three lines in home directory:
[pypi]
username = __token__
password = <your pypi API token>
Shaded line should be modified for your application. Make sure that username is not your username, but __token__.
Finally, it is ready to upload the necessary three files to debut a PyPI package.
$ python setup.py install
$ python setup.py sdist bdist_wheel
You need to install twine library to upload three files.
$ pip install twine
Then, finally upload files to pypi site by the following command:
$ twine upload dist/*