Amina109
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Make a copy
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Make a copy Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    # DNS server on CentOS ## Introduction One of the important services that ensure the functioning of the modern Internet is a DNS, which can be used to resolve host names and IP addresses. This provides a central way to manage hostnames and IP addresses, which is indispensable when an environment expands to multiple hosts. In this work, we use BIND9 suite running on CentOS 7 to set up the public DNS server with its own zone of responsibility. ## Goal/Tasks of the Project This project is aimed to help us: - understand and revise the basic concepts of DNS - get hands-on experience with CentOS, which uses Red Hat's source code to create a final product very similar to RHEL. - understand how to work with BIND (version 9) - create our own public DNS server, that is responsible for its own zone ## Steps of the solution 1. Get VPC instance from Amazon Web Services (AWS), choose **CentOS** as operating system (referred to as `dns-server`) 2. Get domain name `vavk.ga` and specify IP address of `dns-server` as a resolving DNS 3. Get another VPC instance from AWS that would act as `web-server` with our domain name 4. Install BIND on the `dns-server` and configure it (so that it would be able to handle queries about our domain and about other domains) - Open the port #53 to enable DNS queries - Set up DNS as recursive - Create localhost zone - Create forward resolution zone for `vavk.ga` and DNS server - Create reverse resolution for `vavk.ga` and DNS server - Create root resolution zone 5. Test that everything works as expected ## Prerequisites ### Configuring AWS instance <div style="display: flex; flex-wrap: wrap;"> <div style="margin-right: 20px; margin-bottom: 20px; width: 350px;"> <img src="https://i.imgur.com/SHJc3fQ.png" width="100%" /> </div> <div style="width: 350px; margin-bottom: 20px;"> Sign up to AWS service account and choose EC2 option. </div> </div> <div style="display: flex; flex-wrap: wrap;"> <div style="margin-right: 20px; margin-bottom: 20px; width: 350px;"> <img src="https://i.imgur.com/LLHLGVM.png" width="100%" /> </div> <div style="width: 350px; margin-bottom: 20px;"> Choose launch instance, then specify the choice: launch instance from template. </div> </div> <div style="display: flex; flex-wrap: wrap;"> <div style="margin-right: 20px; margin-bottom: 20px; width: 350px;"> <img src="https://i.imgur.com/kkrik3I.png" width="100%" /> </div> <div style="width: 350px; margin-bottom: 20px;"> In the first step search <i>centos.</i> </div> </div> <div style="display: flex; flex-wrap: wrap;"> <div style="margin-right: 20px; margin-bottom: 20px; width: 350px;"> <img src="https://i.imgur.com/nEwvHIU.png" width="100%" /> </div> <div style="width: 350px; margin-bottom: 20px;"> We do not need to specify anything, just choose to proceed. </div> </div> <div style="display: flex; flex-wrap: wrap;"> <div style="margin-right: 20px; margin-bottom: 20px; width: 350px;"> <img src="https://i.imgur.com/FlwE2xo.png" width="100%" /> </div> <div style="width: 350px; margin-bottom: 20px;"> At the second step choose t2.micro as an instance type, press next. </div> </div> <div style="display: flex; flex-wrap: wrap;"> <div style="margin-right: 20px; margin-bottom: 20px; width: 350px;"> <img src="https://i.imgur.com/vImyd29.png" width="100%" /> </div> <div style="width: 350px; margin-bottom: 20px;"> The next one goes mainly as default, only choose to enable resource-based IPv4 DNS requests. </div> </div> <div style="display: flex; flex-wrap: wrap;"> <div style="margin-right: 20px; margin-bottom: 20px; width: 350px;"> <img src="https://i.imgur.com/JU5dKPa.png" width="100%" /> </div> <div style="width: 350px; margin-bottom: 20px;"> The next half of the Instance Details Configuration is also left as the default. As well as the 4 Step - "Add Storage". </div> </div> <div style="display: flex; flex-wrap: wrap;"> <div style="margin-right: 20px; margin-bottom: 20px; width: 350px;"> <img src="https://i.imgur.com/QYEIWHR.png" width="100%" /> </div> <div style="width: 350px; margin-bottom: 20px;"> THe 5th step is for configuring tags, we are not adding any of them. </div> </div> <div style="display: flex; flex-wrap: wrap;"> <div style="margin-right: 20px; margin-bottom: 20px; width: 350px;"> <img src="https://i.imgur.com/aLokvTf.png" width="100%" /> </div> <div style="width: 350px; margin-bottom: 20px;"> The sixth step is for configuring Security Group. We are choosing to create the one that was recommended by AWS Marketplace: we are adding the rule for SSH (which grants access for all IPs). </div> </div> <div style="display: flex; flex-wrap: wrap;"> <div style="margin-right: 20px; margin-bottom: 20px; width: 350px;"> <img src="https://i.imgur.com/F5YuDRI.png" width="100%" /> </div> <div style="width: 350px; margin-bottom: 20px;"> Later the rules were enhanced by adding the rule for DNS(UDP and TCP) access for all IPs on port 53. It can be done by sticking to the following path: <i>"EC2" -> "Network & Security" -> "Securiry Groups" -> Your Security Group -> "Edit inbound rules" </i> </div> </div> <div style="display: flex; flex-wrap: wrap;"> <div style="margin-right: 20px; margin-bottom: 20px; width: 350px;"> <img src="https://i.imgur.com/diXBT6Y.png" width="100%" /> </div> <div style="width: 350px; margin-bottom: 20px;"> At the 7th step we are creating an RSA key pair called <i>VavkCentOS</i> in .pem format. </div> </div> <div style="display: flex; flex-wrap: wrap;"> <div style="margin-right: 20px; margin-bottom: 20px; width: 350px;"> <img src="https://i.imgur.com/W90T0k1.png" width="100%" /> </div> <div style="width: 350px; margin-bottom: 20px;"> To find the public IPv4 address, follow the path: <i>"EC2" -> "Instances" -> Your Instance</i> </div> </div> ### Getting domain <div style="display: flex; flex-wrap: wrap;"> <div style="margin-right: 20px; margin-bottom: 20px; width: 350px;"> <img src="https://i.imgur.com/R5Q9DpP.png" width="100%" /> </div> <div style="width: 350px; margin-bottom: 20px;"> To get free domain we used <a href="http://www.dot.tk/ru/index.html?lang=ru">dot.tk</a> website. </div> </div> <div style="display: flex; flex-wrap: wrap;"> <div style="margin-right: 20px; margin-bottom: 20px; width: 350px;"> <img src="https://i.imgur.com/XqsjYXz.png" width="100%" /> </div> <div style="width: 350px; margin-bottom: 20px;"> We found some unused domain ("vavk.ga") name and took it. </div> </div> <div style="display: flex; flex-wrap: wrap;"> <div style="margin-right: 20px; margin-bottom: 20px; width: 350px;"> <img src="https://i.imgur.com/Jz1bMpH.png" width="100%" /> </div> <div style="width: 350px; margin-bottom: 20px;"> The next step was to configure our domain. We chose "Use your own DNS" option. Then we filled in all the required fields including Nameserver and IP address. </div> </div> And, finally, we added our detailed information. However, this is done only to complete the registration and make an order for the domain, so we have indicated random facts in the fields. <p align="center"> <img src="https://i.imgur.com/DCNAJIK.png" width="350" /> <img src="https://i.imgur.com/u5E7ORi.png" width="350" /> </p> </br> ### Connecting to AWS Connecting to AWS is done differently on OSX and Windows. #### OSX On OSX one can simply use the command provided by AWS itself `ssh -i "<Your key, generated on step7>" <hostname>@<Public IP>`, in our case `ssh -i "VavkCentOS.pem" centos@3.23.129.27`. (AWS tutorial is available above) <img src="https://i.imgur.com/Sl6XyxG.png" width="450" /> #### Windows 1. Open **PuTTY Key Generator** and load a downloaded`.pem` file. Save private key, which is now in `.ppk` format. 2. Use it in **PuTTY Configuration**. Enter public IP of the machine, go to `SSH -> Auth` section on the left side menu and add you `.ppk` key, press `open`. <img src="https://i.imgur.com/WnIQxHV.jpg" width="350" /> <img src="https://i.imgur.com/hpNPnpZ.jpg" width="350" /> ### Install BIND on DNS Servers with `yum`: `sudo yum install bind bind-utils` <p align="center"> <img src="https://i.imgur.com/Sm5HL4G.png" width="350" /> <img src="https://i.imgur.com/gdfe0Av.png" width="350" /> </p> ## Configure Bind After bind was installed successfully, open the `named.conf` file for editing: `sudo nano /etc/named.conf` **Note**: we are configuring DNS to be responsible for `vavk.ga` zone Here is our configuration: ``` options { listen-on port 53 { any; }; directory "/var/named"; dump-file "/var/named/data/cache_dump.db"; statistics-file "/var/named/data/named_stats.txt"; memstatistics-file "/var/named/data/named_mem_stats.txt"; recursing-file "/var/named/data/named.recursing"; secroots-file "/var/named/data/named.secroots"; allow-query { any; }; allow-query-cache { any;}; recursion yes; /* Path to ISC DLV key */ bindkeys-file "/etc/named.root.key"; managed-keys-directory "/var/named/dynamic"; pid-file "/run/named/named.pid"; session-keyfile "/run/named/session.key"; }; logging { channel default_debug { file "data/named.run"; severity dynamic; }; }; zone "vavk.ga" IN { type master; file "db.vavk.ga.test"; }; zone "77.179.15.52.in-addr.arpa." IN { type master; file "db.52.15.179.77"; }; zone "27.129.23.3.in-addr.arpa." IN { type master; file "db.3.23.129.27"; }; zone "." IN { type hint; file "named.ca"; }; include "/etc/named.local"; include "/etc/named.root.key"; ``` - `listen-on port 53 { any; };` Listen on port 53 from any interface (be it localhost or public IP) - `directory "/var/named";` Directory, where the zone configuration files are stored - `recursion yes` Allows recursion on DNS server - `allow-query { any; };` Allow any hosts to query our DNS about records it is responsible for. Not very secure, though. - `allow-query-cache { any; };` allow-query-cache is used to specify access to the cache and recursive queries on the DNS. Now, all hosts can ask our dns for any record, not just the ones it is responsible for. ### Including zones ``` zone "vavk.ga" IN { type master; file "db.vavk.ga.test"; }; ``` `type master` tells that out DNS is a primary one for the zone `vavk.ga`, the zone file and configuration is stored in `db.vavk.ga.test` file. ``` zone "77.179.15.52.in-addr.arpa." IN { type master; file "db.52.15.179.77"; }; zone "27.129.23.3.in-addr.arpa." IN { type master; file "db.3.23.129.27"; }; ``` Both are reverse zones that our DNS should be able to perform a translation `IP to Hostname`. `52.15.179.77` is the IP of our web-app `vrubel.vavk.ga` and `3.23.129.27` is the IP of our DNS server and web-app `van.gogh.vavk.ga`. **Note**: It is worth pointing out, that globally Amazon is responsible for these IPs. And in order to take over this responsibility, we need to be the owner of an IP. Therefore, if we query not our server about reverse translation, we will get a canonical amazon name of the machine. If we ask our DNS directly, resolution is as intended. ![](https://i.imgur.com/jWajQcK.png) ``` zone "." IN { type hint; file "named.ca"; }; ``` Root zone, which DNS server can get *hints* from to resolve any name. Bind9 is provisioned with `named.ca` file, which contains root dns and is updated occasionally. ``` include "/etc/named.local"; include "/etc/named.root.key"; ``` With these lines we include local zone resolution file + a secure root key file. ### Localhost zonefile ``` zone "localhost"{ # forward zone type master; file "localhost.zone"; }; zone "0.0.127.in-addr.arpa" { # reverse zone type master; file "0.0.127.zone"; }; ``` `0.0.127.zone` and `localhost.zone` are preloaded into Bind9. ![](https://i.imgur.com/YyglNo4.png) ### `vavk.ga` zonefile ``` $TTL 86400 ; 1 day vavk.ga. IN SOA ns1.vavk.ga. vovablink1@gmail.com. ( 57 28800 7200 2419200 86400 ) vavk.ga. IN NS ns1.vavk.ga. ; Nameservers responsible for the zone vavk.ga. IN NS ns2.vavk.ga. ns1.vavk.ga. IN A 3.23.129.27 ; Namesevers' IPs ns2.vavk.ga. IN A 3.23.129.27 vrubel.vavk.ga. IN A 52.15.179.77 ; IPs of 2 web-application in vavk.ga zone van.gogh.vavk.ga. IN A 3.23.129.27 ``` The numbers represent the time parameter for a record. For example, `TTL 86400` means that the record is cached for 86400 seconds, which is 1 day. In another file, we will show how one can specify these time parameters in a user-friendly way (without calculating seconds). `vavk.ga. IN SOA ns1.vavk.ga. vovablink1@gmail.com.` tells that name server with hostname `ns1.vavk.ga.` is responsible for this zone, and `vovablink1@gmail.com` is the admin's email of the zone. ### Reverse-zone files Here, time is specified in user-friendly format. **File: db.3.23.129.27** ``` $TTL 3H @ IN SOA ns1.vavk.ga. vovablink1@gmail.com ( 1 3H 1H 1W 1H ) # blank space means same address as a zone IN NS ns1.vavk.ga. # responsible name servers IN NS ns2.vavk.ga. PTR van.gogh.vavk.ga. # DomainName -> IP translation record (web-app name) PTR ns1.vavk.ga. # DomainName -> IP translation record (dns name) ``` **File: db.52.15.179.77** ``` $TTL 3H @ IN SOA ns1.vavk.ga. vovablink1@gmail.com ( 1 3H 1H 1W 1H ) IN NS ns1.vavk.ga. IN NS ns2.vavk.ga. PTR vrubel.vavk.ga. ``` ## Starting DNS 1) Check that higher level domain (.ga in our case) contains a record about our dns server and zone. Use this [webpage](https://www.iana.org/domains/root/db/ga.html) to find IP of higher level domain and execute `nslookup -type=NS <your zone> <IP of higher level domain>` (in our case `nslookup -type=NS vavk.ga 185.21.171.49`) ![](https://i.imgur.com/8PNOLq9.png) 1) In order to start a DNS server, it is crucial to open port 53 not only on AWS, but inside the machine. This is done with commands: ``` firewall-cmd --permanent --zone=public --add-port=53/tcp firewall-cmd --permanent --zone=public --add-port=53/udp firewall-cmd --reload ``` 2) After that, check that the port is open with command `sudo nmap -sT -p 53 <IP of DNS>` ![](https://i.imgur.com/DoJ3IBy.png) 3) Check that code has no syntax errors: `sudo named-checkconf`. If no output is provided, then everything is ok 4) `sudo systemctl enable named` automatically starts `named` on boot 5) `sudo systemctl start named` starts `named` right now In case of an error, use `sudo systemctl status named` to see the error trace. If previous steps are successful, you should see the following: ![](https://i.imgur.com/OBR5kbx.png) ## Demo [Video demo (Christmas special edition)](https://www.youtube.com/watch?v=yAeP0FDQOCY) ## Testing With `nslookup`, we ensured that our DNS server: * responds to requests about its zone and about outer domains, * performs caching (disabling and enabling recursion), * replies on reverse DNS queries about its zone. With `dig +trace`, we saw how the hierarchy of DNS servers works with the query about our domain name (`van.gogh.vavk.ga.` -> root servers, `.ga` servers, and our server `ns1.vavk.ga.`) ![](https://i.imgur.com/my2IvHh.png) ![](https://i.imgur.com/WYrfihv.png) Refer to demo video for further details. ## Difficulties faced * **Problem (Understanding what to do)** * At first we had to understand our goal and how to accomplish it. * **Problem (How to find IP of a domain name)** * **Description:** We got a domain name, but we thought that IP had to come with it automatically. * **Solution:** Only afterwards we understood that we had to get an additional VPC with public IP and assign domain name to it. (Domain name is just a domain name, not a runing web-application). * **Problem (BIND versions)** * We found several tutorials on setting DNS server with BIND, however, due to difference in versions of BIND, there were contradictory pieces, which we had to try in different combinations to get a working result. * **Problem (Testing)** * **Evidence**: `nslookup <any outer domain name> 3.23.129.29` yields answers from both remote and local machines, `nslookup <our domain name> 3.23.129.29` doesn't work from remote machines, and works locally. * **Problem & Solution**: port 53 was blocked by firewall of the AWS inctance DNS ran on. From now, `nslookup <our domain name> 3.23.129.29` works from any machine, and our domain name is globally discoverable. * **Question**: before we opened the port, we still got answers to `nslookup <any outer domain name> 3.23.129.29`, why? * **Evidence**: `nslookup` always responds with non-authoritative answer; `nslookup <our domain name> <random IP address>` works (and behaviour of `dig` is analogous) * **Improvement**: Googling for "ways to ask *specific* DNS server" proposed the following: `nslookup -all -debug -type=ANY -class=ANY vavk.ga 3.23.129.27`. * **Evidence**: with the new way to send requests, our DNS server responded only to requests about our zone; requests about external domains resulted in `SERVFAIL`. * **Solution**: Enabling recursion and allowing-query-cache not only from `localhost`, but from `any` IP address. From now all forward requests to our DNS server were successful, and requests to arbitrary IP addresses were failing, as expected. * **Challenge**: then we had to come up with the query for reverse zones (those strange flags were cumbersome, and not using them made command disregard specified domain name). * **Deus ex machina**: we tried `nslookup` not only from WSL and OSX, but from VPC instance that acted as web-server (on Ubuntu), and discovered, that nslookup has different behavior there: ![](https://i.imgur.com/nqy9NRR.png) ![](https://i.imgur.com/LsYnxm6.png) So, `nslookup` and `dig` work as expected on Ubuntu and provide **strange behavior** on other operating systems. * **Takeaway**: we continued to test our DNS server from the Ubuntu VPC instance. * **Problem (Root hints file)** * **Description:** We had downloaded `root.list` file that contained information about root servers, but `named` would not start, giving an `Permission denied` error. * **Solution:** BIND 9 has a file`named.ca`, which contains root hints, so inculding it solved the issue. * **Problem (DNS would not respond about external IPs)** * **Description:** When we learned how to ask our DNS server specifically (and truly), started to fail requests about external domain names ![](https://i.imgur.com/Hh8mz1m.png) * **Solution:** Recursion for external IPs trabslation was not allowed. `allow-query-cache { any; };` solved the issue. ## Conclusion, contemplations and judgement This project was indeed a challenge that took us a considerable amount of time to complete. However, it really helped to learn something new and to put the course knowledge into practice. We have done some pretty basic functionality and there are still many aspects of our work that can be implemented. **Accomplished:** * Understood how to work with AWS * Created our own domains and run web-apps * Understood how to work with CentOS * Understood main features of BIND9 * Created a public DNS server * Found out that `nslookup` and `dig` are not properly implemented on WSL and OSX **Perspective:** * Create a slave dns server for zone transfer * Understand the reverse IP resolution in more detail **Acknowledgements:** * We want to thank our mentor *Kirill Saltanov* for guiding and accompanying us during our project. Without his help and insight, we wouldn't be able to tackle this project. ## References 1. [Habr tutorial on DNS with BIND](https://habr.com/ru/sandbox/21144/) 1. [Tutorial on local DNS configuration](https://www.hostinger.com/tutorials/how-to-use-the-dig-command-in-linux/) 1. [BIND 9 documentation](https://bind9.readthedocs.io/en/latest/) 1. [BIND manual](https://docstore.mik.ua/orelly/networking_2ndEd/dns/ch04_01.htm) 1. [Oracle documentation](https://docs.oracle.com/en/operating-systems/oracle-linux/6/admin/about-resource-records.html#) 1. [Where to find root dns IPs for `.ga`](https://www.iana.org/domains/root/db/ga.html) 1. [DNS Troubleshooting](https://tools.ietf.org/id/draft-ietf-dnsop-no-response-issue-12.html) ## Appendix <a id="appendix"></a> ### Useful commands We found several commands useful: `nslookup -all -debug -type=ANY -class=ANY vavk.ga 3.23.129.27` — ask *particular* nameserver about some domain name. Note that `dig @3.23.129.27 vavk.ga` somehow ignores provided ip address of the nameserver, and successfully performs a lookup, even if ip address of the nameserver is modified. `sudo nmap -sT -p 53 185.21.171.49` — check status of particular port of machine with the given ip adddress `nslookup -type=soa vavk.ga` — find an authoritative server for the given zone `dig vavk.ga NS` or `nslookup -type=ns vavk.ga` — find NS entries for some domain name. We could also specify nameserver responsible for .ga, however it seems to be ignored. `host 3.23.129.27`, `dig -x 3.23.129.27`, `nslookup 3.23.129.27` or `nslookup -type=ptr 3.23.129.27` for reverse DNS queries

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully